PageSourceSearch

https://www.unk.edu/calendar/_files/js/hh-events.js

js unk.edu collected 2026-09-24 08:57:08 UTC 111,651 bytes, 2,393 lines download raw bytes

1/* calendar */
2var urlHashes = ['v=', 'f1=', 'f2=', 'f3=', 'f4=', 'f5=', 'f6=', 'f7=', 'f8=', 'f9=', 'f10='];
3var vHashes = [];
4var f1Hashes = [];
5var f2Hashes = [];
6var f3Hashes = [];
7var f4Hashes = [];
8var f5Hashes = [];
9var f6Hashes = [];
10var f7Hashes = [];
11var f8Hashes = [];
12var f9Hashes = [];
13var f10Hashes = [];
14var allHashes = "";
15var today = moment();
16var currentDate = today.format('D');
17var currentMonth = today.format('MM');
18var currentYear = today.format('YYYY');
19var nextMonth = today.add(1, 'month').format('MM');
20if (nextMonth == "01") {
21    var nextMonthYear = today.add(1, 'year').format('YYYY');
22} else {
23    var nextMonthYear = today.format('YYYY');
24}
25var previousMonth = today.subtract(1, 'month').format('MM');
26if (previousMonth == "12") {
27    var previousMonthYear = today.subtract(1, 'year').format('YYYY');
28} else {
29    var previousMonthYear = today.format('YYYY');
30}
31var checkedEvents = [];
32var allData = [];
33var allDataURLs = [];
34var currentDataURLs = [];
35var currentData = [];
36var sideFeatures = [];
37var sideFeaturesURL = [];
38var currentLoadedView = defaultView;
39var lastLoadedMonth = "";
40var lastLoadedYear = "";
41var currentURL = window.location.href;
42var hash = "";
43var newHash = "";
44var hashClass = "";
45var hashArray = [];
46var newHashArray = [];
47var newSetHashArray = [];
48var setFiltersLoad = "";
49var $eventsContainer = $(".events .events-list");
50var $featuredEventsContainer = $(".featured-events-list");
51var eventList = "";
52var eventItem = "";
53var $loadMoreContainer = $(".events .load-more");
54var $eventViewHeader = $("#events-view");
55var $eventViewCountDisplay = $(".events-results .event-count");
56var $eventFilterViewCountDisplay = $(".events-results .filter-count");
57var $eventsMessageContainer = $(".events-results .events-message");
58var eventsMessage = "";
59var errorMessage = false;
60var rangeDates = [];
61var rangeDateStart = "";
62var rangeDateEnd = "";
63var startYearRange = "";
64var endYearRange = "";
65var startMonthRange = "";
66var endMonthRange = "";
67var startDayRange = "";
68var endDayRange = "";
69var singleDate = "";
70var singleDateYear = "";
71var singleDateMonth = "";
72var singleDateDay = "";
73var startDate = "";
74var endDate = "";
75var separator = '<span class="separator" aria-hidden="true">•</span><span class="sr-only">, </span>';
76
77$(document).ready(function() {
78     if ($('.events-listing').length) {
79        $('#events-loaded').text("Loading events...");
80        $('#mini-calendar .input-daterange').datepicker({
81            todayHighlight: true,
82            container: 'body',
83            orientation: 'bottom auto',
84        });
85        $('#startDate').on('changeDate', function(startDateData) {
86            $eventsContainer.empty();
87            startDate = moment(startDateData.date).format("MM/DD/YYYY");
88            if (endDate == "" || endDate == startDate) {
89                setHash("v=", "replace", startDate, function() {
90                    eventCount();
91                    loadView(startDate).then(function(results) {
92                        showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
93                    });
94                });
95            } else {
96                setHash("v=", "replace", startDate + "-" + endDate, function() {
97                    eventCount();
98                    loadView(startDate + "-" + endDate).then(function(results) {
99                        showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
100                    });
101                });
102            }
103        });
104        $('#endDate').on('changeDate', function(endDateData) {
105            $eventsContainer.empty();
106            if (startDate != "") {
107                endDate = moment(endDateData.date).format("MM/DD/YYYY");
108                if (startDate == endDate) {
109                    setHash("v=", "replace", startDate, function() {
110                        loadView(startDate).then(function(results) {
111                            showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
112                        });
113                    });
114                } else {
115                    setHash("v=", "replace", startDate + "-" + endDate, function() {
116                        loadView(startDate + "-" + endDate).then(function(results) {
117                            showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
118                        });
119                    });
120                }
121            }
122        });
123        $(".date-views button").click(function() {
124            $(".date-views button").each(function() {
125                $(this).removeClass("active");
126            });
127            $(this).addClass("active");
128        });
129        $eventsContainer.tooltip({
130            selector: "[data-toggle='tooltip']"
131        });
132        $(".hh-events .plus-toggle").on("click keydown", function (e) {
133            // Trigger on click, Enter, or Space
134            if (e.type === "click" || e.key === "Enter" || e.key === " ") {
135                if (e.key) e.preventDefault(); // prevent scrolling on Space
136        
137                const $sidebar = $("#sidebar-panel"); // target sidebar by ID
138                const $btn = $(this);
139        
140                // Determine next state from button's aria-expanded
141                const isExpanded = $btn.attr("aria-expanded") === "fal
141se";
142        
143                // Toggle sidebar classes separately
144                $sidebar.toggleClass("expanded", isExpanded);
145                $sidebar.toggleClass("collapsed", !isExpanded);
146        
147                // Update all toggle buttons in sync
148                $(".hh-events .plus-toggle").each(function () {
149                    $(this)
150                        .attr("aria-expanded", isExpanded)
151                        .attr("title", isExpanded ? "Collapse" : "Expand")
152                        .find("span.sr-only").text(isExpanded ? "Collapse" : "Expand");
153        
154                    // Swap the icon
155                    $(this).find("i")
156                           .removeClass("fa-plus-circle fa-minus-circle")
157                           .addClass(isExpanded ? "fa-minus-circle" : "fa-plus-circle");
158                });
159                
160                // Update accessibility after toggle
161                updateSidebarAccessibility();
162            }
163        });
164        $(".checkboxes input").on('click', function() {
165            $(this).blur();
166        });
167        $('.checkboxes input[type="checkbox"]').not('.dropdown-menu input[type="checkbox"]').on('keydown', function(e) {
168            if (e.key === 'Enter') {
169                e.preventDefault(); // prevent form submission or weird behavior
170                $(this).click();    // triggers normal checkbox toggle + your filtering
171            }
172        });
173        $(".events").on('click', '.loadMoreEvents', function() {
174            if (debugMode) {
175                console.log("------------------------");
176                console.log("loadMoreEvents");
177            }
178            showEvents(currentData, currentLoadedView, $eventsContainer, loadMoreCount, "loadMore");
179            searchText($("#search-events").val().toLowerCase());
180        });
181        $(".events").on('click', '.loadAllEvents', function() {
182            if (debugMode) {
183                console.log("------------------------");
184                console.log("loadAllEvents");
185            }
186            showEvents(currentData, currentLoadedView, $eventsContainer, "all", "loadAll");
187            searchText($("#search-events").val().toLowerCase());
188        });
189        $(".clearAll").on("click", function() {
190            if (debugMode) {
191                console.log("------------------------");
192                console.log("clearAll");
193            }
194            $(this).blur();
195            $eventFilterViewCountDisplay.empty();
196            $eventViewCountDisplay.empty();
197            $('.input-daterange input').datepicker('update', null);
198            $('.input-daterange').datepicker('updateDates');
199            removeHash();
200            $("#search-events").val('');
201            setViewsLoad = "";
202            setFiltersLoad = "";
203            $("select.loadFilter").val("*");
204            $(".loadFilter:checkbox:checked").each(function() {
205                $(this).prop("checked", false);
206            });
207            $(".date-views button").each(function() {
208                $(this).removeClass("active");
209            });
210            loadView(defaultView, "", "", "clearAll").then(function(results) {
211                showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
212            });
213        });
214        checkHash();
215        $(window).on('popstate', function() {
216            checkHash();
217        });
218        $(window).on("resize", function() {
219            updateSidebarAccessibility();
220        });
221        $('#datepicker').datepicker().on('changeMonth changeYear show', function () {
222            $('.datepicker-days td.day').each(function () {
223                const timestamp = $(this).data('date');
224                if (!timestamp) return;
225        
226                const date = new Date(parseInt(timestamp, 10));
227        
228                const formatted = date.toLocaleDateString('en-US', {
229                    year: 'numeric',
230                    month: 'long',
231                    day: 'numeric'
232                });
233        
234                $(this).attr('aria-label', formatted);
235            });
236        });
237        $('#skip-events').on('click', function(e) {
238            e.preventDefault();          // stop default anchor behavior
239            $('#after-events').focus();  // explicitly focus the placeholder
240        });
241        $('a[href="#skip-events"]').on('click', function(e) {
242            e.preventDefault();
243            $('#skip-events').focus();
244        });
245        $('.dropdown').each(function() {
246            const $dropdown = $(this);
247            const $toggle = $dropdown.find('.dropdown-toggle');
248            const $menu = $dropdown.find('.dropdown-menu');
249            const $options = $menu.find('input[type="checkbox"]');
250        
251            function openDropdown() {
252                $dropdown.addClass('open');
253                $menu.addClass('open');
254                $toggle.attr('aria-expanded', 'true');
255                $toggle.attr('aria-label', $toggle.text().trim() + ', expanded');
256            }
257        
258            function closeDropdown() {
259                $dropdown.removeClass('open');
260                $menu.removeClass('open');
261                $toggle.attr('aria-expanded', 'false');
262                $toggle.attr('aria-label', $toggle.text().trim() + ', collapsed');
263            }
264        
265            $menu.on('click', function(e) {
266                e.stopPropagation();
267            });
268        
269            $menu.on('click', 'label', function(e) {
270                e.stopImmediatePropagation();
271            });
272        
273            // Toggle button: keyboard only (let Bootstrap handle click)
274            $toggle.on('keydown', function(e) {
275                if (e.key === 'Enter' || e.key === ' ') {
276                    e.preventDefault();
277                    e.stopImmediatePropagation();
278                    if ($dropdown.hasClass('open')) {
279                        closeDropdown();
280                    } else {
281                        openDropdown();
282                    }
283                } else if (e.key === 'Escape') {
284                    e.preventDefault();
285                    e.stopImmediatePropagation();
286                    closeDropdown();
287                }
288            });
289        
290            // Options navigation
291            $options.on('keydown', function(e) {
292                const idx = $options.index(this);
293                switch(e.key) {
294                    case 'ArrowDown':
295                        e.preventDefault();
296                        $options.eq((idx + 1) % $options.length).focus();
297                        break;
298                    case 'ArrowUp':
299                        e.preventDefault();
300                        $options.eq((idx - 1 + $options.length) % $options.length).focus();
301                        break;
302                    case 'Home':
303                        e.preventDefault();
304                        $options.first().focus();
305                        break;
306                    case 'End':
307                        e.preventDefault();
308                        $options.last().focus();
309                        break;
310                    case 'Enter':
311                        e.preventDefault();
312                        $(this).prop('checked', !$(this).prop('checked')).trigger('change', { fromKeyboard: true });
313                        $(this).focus();
314                        break;
315                    case ' ':
316                        e.preventDefault();
317                        $(this).prop('checked', !$(this).prop('checked')).trigger('change', { fromKeyboard: true });
318                        $(this).focus();
319                        break;
320                    case 'Escape':
321                        e.preventDefault();
322                        closeDropdown();
323                        $toggle.focus();
324                        break;
325                }
326            });
327        
328            // Close on focusout for keyboard users only
329            $menu.on('focusout', function(e) {
330                if (e.relatedTarget && !$menu[0].contains(e.relatedTarget)) {
331                    closeDropdown();
332                }
333            });
334        
335            let isClosing = false;
336            $toggle.on('mousedown', function() {
337                if ($dropdown.hasClass('open')) {
338                    isClosing = true;
339                }
340            });
341            $dropdown.on('shown.bs.dropdown', function() {
342                if (isClosing) {
343                    closeDropdown();
344                    isClosing = false;
345                } else {
346                    $toggle.attr('aria-label', $toggle.text().trim() + ', expanded');
347                }
348            });
349            $dropdown.on('hidden.bs.dropdown', function() {
350                isClosing = false;
351                $toggle.attr('aria-label', $toggle.text().trim() + ', collapsed');
352            });
353        });
354    }
355    if ($('.events-detail').length) {
356        $('.events-detail').tooltip({
357            selector: "[data-toggle='tooltip']"
358        });
359        if ($('.events-detail .sTime').length) {
360            var sZone = moment.tz.guess();
361            var sTimezone = moment.tz(thisCurrentEvent[0].startDate, sZone).format("z");
362            $(".events-detail .sTime").append(timeOutput(thisCurrentEvent[0].startDate, thisCurrentEvent[0].endDate, thisCurrentEvent[0].allDay, thisCurrentEvent[0].originalStart, thisCurrentEvent[0].originalEnd));
363            if (thisCurrentEvent[0].allDay != "true") {
364                $(".events-detail .sTime").append(" " + sTimezone);
365            }
366        }
367        if ($('.events-detail .rDate').length) {
368            currentRecurringEvent();
369            $("#rDates").change(function(e) {
370                $(".save-row .feeds").empty();
371                $(".save-row .feeds").append(saveLinkOutput($(this).find(':selected').data('title'), $(this).find(':selected').data('desc'), $(this).find(':selected').data('start'), $(this).find(':selected').data('end'), $(this).find(':selected').data('timezone'), $(this).find(':selected').data('allDay'), "google"));
372                $(".save-row .feeds").append(saveLinkOutput($(this).find(':selected').data('title'), $(this).find(':selected').data('desc'), $(this).find(':selected').data('start'), $(this).find(':selected').data('end'), $(this).find(':selected').data('timezone'), $(this).find(':selected').data('allDay'), "outlook"));
373                $(".save-row .feeds").append(saveLinkOutput($(this).find(':selected').data('title'), $(this).find(':selected').data('desc'), $(this).find(':selected').data('start'), $(this).find(':selected').data('end'), $(this).find(':selected').data('timezone'), $(this).find(':selected').data('allDay'), "yahoo"));
374                $(".save-row .feeds").append(saveLinkOutput($(this).find(':selected').data('title'), $(this).find(':selected').data('desc'), $(this).find(':selected').data('start'), $(this).find(':selected').data('end'), $(this).find(':selected').data('timezone'), $(this).find(':selected').data('allDay'), "ics"));
375            });
376            setTimeout(function() {
377                if ($('.events-detail .related-events').length) {
378                    relatedEventsAjax();
379                }
380            }, 300);
381        } else {
382            if ($('.events-detail .related-events').length) {
383                relatedEventsAjax();
384            }
385        }
386    }
387    if ($('.hh-events-block').length) {
388        blockEvents();
389    }
390});
391
392function updateSidebarAccessibility() {
393    const $sidebar = $("#sidebar-panel");
394    const $overlay = $sidebar.find(".gradient-overlay");
395    const isCollapsed = $sidebar.hasClass("collapsed");
396    const isMobile = window.matchMedia("(max-width: 991px)").matches;
397
398    if (isMobile) {
399        // On mobile, collapsed = hidden & not tabbable
400        $overlay.attr("aria-hidden", isCollapsed);
401        if (isCollapsed) {
402            $overlay.attr("tabindex", "-1"); // prevent container focus
403        } else {
404            $overlay.removeAttr("tabindex"); // remove entirely
405        }
406        $overlay.find('a, button, input, select, textarea, [tabindex]').each(function() {
407            $(this).attr('tabindex', isCollapsed ? '-1' : '0');
408        });
409    } else {
410        // On desktop, always visible & tabbable
411        $overlay.attr("aria-hidden", false);
412        $overlay.removeAttr("tabindex");
413        $overlay.find('a, button, input, select, textarea, [tabindex]').each(function() {
414            $(this).removeAttr('tabindex');
415        });
416    }
417}
418
419/* data */
420
421function checkDataURLs(data, view, target, showLimit, origin) {
422    return new Promise(function(resolve, reject) {
423        if (debugMode) {
424            console.log("checkDataURLs");
425        }
426        awaitAll(data, getDataFromURLs).then(function(results) {
427            var URLData = [];
428            for (let i = 0; i < results.length; i++) {
429                URLData = URLData.concat(results[i]);
430            }
431            URLData = _.uniqBy(URLData, 'id');
432            calculateRecurrences(URLData).then(function(resultsR) {
433                eventDateChecker(URLData, resultsR, view).then(function(results) {
434                    jsonToCurrentData(results).then(function(results) {
435                        results.jsonToCurrentDataEvents.sort(function(a, b) {
436                            return +new Date(a.startDate) - +new Date(b.startDate);
437                        });
438                        resolve({
439                            "events": results.jsonToCurrentDataEvents,
440                            "view": view,
441                            "target": target,
442                            "showLimit": showLimit,
443                            "origin": origin
444                        });
445                    });
446                });
447            });
448        });
449    })
450}
451
452function getFeaturedDataFromURLs(currentDataURL) {
453    return new Promise(function(resolve, reject) {
454        if (debugMode) {
455            console.log("getFeaturedDataFromURLs: " + currentDataURL);
456        }
457        $.ajax({
458            url: currentDataURL,
459            success: function(data) {
460                resolve(data.events);
461            },
462            error: function(data) {
463                if (data.status == 200) {
464                    resolve({
465                        Error: "JSON Not Valid: " + currentDataURL
466                    });
467                    console.log("JSON Not Valid: " + currentDataURL);
468                } else {
469                    resolve({
470                        Error: "Data URL Not Found: " + currentDataURL
471                    });
472                    console.log("Data URL Not Found: " + currentDataURL);
473                }
474            }
475        });
476    })
477}
478
479function getDataFromURLs(currentDataURL) {
480    return new Promise(function(resolve, reject) {
481        if (_.includes(allDataURLs, currentDataURL)) {
482            if (debugMode) {
483                console.log("getDataFromURLs bypassed: " + currentDataURL);
484                console.log({
485                    "allDataIn": allData
486                });
487            }
488            resolve(allData);
489        } else {
490            if (debugMode) {
491                console.log("getDataFromURLs: " + currentDataURL);
492            }
493            $.ajax({
494                url: currentDataURL,
495                success: function(data) {
496                    if (debugMode) {
497                        console.log({
498                            "allDataOut": allData
499                        });
500                        console.log({
501                            "newDataIn": data.events
502                        });
503                    }
504                    if(data.events != undefined){
505                        allData = allData.concat(data.events);
506                    }
507                
508                    
509                    // allData = _.filter(allData, _.isEmpty);
510                    if (debugMode) {
511                        console.log({
512                            "allData": allData
513                        });
514                    }
515                    resolve(allData);
516                
517                    // resolve(data.events);
518                    allDataURLs.push(currentDataURL);
519                },
520                error: function(data) {
521                    if (data.status == 200) {
522                        resolve({
523                            Error: "JSON Not Valid: " + currentDataURL
524                        });
525                        console.log("JSON Not Valid: " + currentDataURL);
526                    } else {
527                        resolve({
528                            Error: "Data URL Not Found: " + currentDataURL
529                        });
530                        console.log("Data URL Not Found: " + currentDataURL);
531                    }
532                }
533            });
534        }
535    })
536}
537
538function eventDateChecker(data, dataR, view) {
539    return new Promise(function(resolve, reject) {
540        checkedEvents = [];
541        if (debugMode) {
542            console.log("eventDateChecker: " + view);
543        }
544        if (view === "featured" || view === "side-featured-events") {
545            if (data != undefined && data.length != 0) {
546                for (let i = 0; i < data.length; i++) {
547                    if (data[i] != undefined && data[i].featured == "true" && data[i].recurringEvent != "true") {
548                        eventDateCheck(data[i], view);
549                    }
550                }
551            }
552            if (dataR != undefined && dataR.length != 0) {
553                for (let i = 0; i < dataR.length; i++) {
554                    if (dataR[i] != undefined && dataR[i].featured == "true") {
555                        eventDateCheck(dataR[i], view);
556                    }
557                }
558            }
559        } else {
560            if (data != undefined && data.length != 0) {
561                for (let i = 0; i < data.length; i++) {
562                    if (data[i] != undefined){
563                        if(data[i].recurringEvent != undefined && data[i].recurringEvent != "true") {
564                            eventDateCheck(data[i], view);
565                        }
566                    }
567                }
568            }
569            if (dataR != undefined && dataR.length != 0) {
570                for (let i = 0; i < dataR.length; i++) {
571                    eventDateCheck(dataR[i], view);
572                }
573            }
574        }
575        if (debugMode) {
576            console.log({"checkedEvents": checkedEvents});
577        }
578        resolve(checkedEvents);
579    });
580}
581
582function eventDateCheck(v, view) {
583    if (filterBy == "startDate") {
584        if (v.startDate != undefined) {
585            var startDateM = moment(v.startDate);
586            if (view === "upcoming-events" || view === "featured" || view === "side-featured-events" || view === "related-events" || view === "current-recurring-event" || view === "hh-events-block") {
587                if (startDateM.isSameOrAfter(moment())) {
588                    checkedEvents.push(v);
589                }
590            } else if (view === "today") {
591                if (moment().isSame(startDateM, 'date')) {
592                    checkedEvents.push(v);
593                }
594            } else if (view === "tomorrow") {
595                if (moment(moment().add(1, 'days')).isSame(startDateM, 'date')) {
596                    checkedEvents.push(v);
597                }
598            } else if (view === "this-week") {
599                if (moment(startDateM).isSameOrAfter(moment().weekday(0), "day") && moment(startDateM).isSameOrBefore(moment().weekday(6), "day")) {
600                    checkedEvents.push(v);
601                }
602            } else if (view === "this-weekend") {
603                if (moment(startDateM).isSameOrAfter(moment().weekday(5), "day") && moment(startDateM).isSameOrBefore(moment().weekday(7), "day")) {
604                    checkedEvents.push(v);
605                }
606            } else if (view === "next-week") {
607                if (moment(startDateM).isSameOrAfter(moment().weekday(7), "day") && moment(startDateM).isSameOrBefore(moment().weekday(13), "day")) {
608                    checkedEvents.push(v);
609                }
610            } else if (view === "this-month") {
611                if (moment().isSame(startDateM, 'month')) {
612                    checkedEvents.push(v);
613                }
614            } else if (view === "next-month") {
615                if (moment().add(1, 'months').isSame(startDateM, 'month')) {
616                    checkedEvents.push(v);
617                }
618            } else {
619                if (view === undefined || view == "") {
620                    checkedEvents.push(v);
621                } else {;
622                    if (view.indexOf("-") > -1) {
623                        if (startDateM.isSameOrAfter(moment(rangeDateStart, "MM/DD/YYYY"), 'day') && startDateM.isSameOrBefore(moment(rangeDateEnd, "MM/DD/YYYY"), 'day')) {
624                            checkedEvents.push(v);
625                        }
626                    } else {
627                        if (startDateM.isSame(moment(view, "MM/DD/YYYY"), "day")) {
628                            checkedEvents.push(v);
629                        }
630                    }
631                }
632            }
633        }
634    } else { // All dates are inclusive dates (square '[]' brackets in isBetween means inclusive)
635        if (v.startDate != undefined && v.endDate != undefined) {
636            var startDateM = moment(v.startDate);
637            var endDateM = moment(v.endDate);
638            if (view === "upcoming-events" || view === "featured" || view === "side-featured-events" || view === "related-events" || view === "current-recurring-event" || view === "hh-events-block") {
639                if (endDateM.isSameOrAfter(moment())) {
640                    checkedEvents.push(v);
641                }
642            } else if (view === "today") { // Today is between start and end date
643                if (moment().isBetween(startDateM, endDateM, 'date', '[]')) {
644                    checkedEvents.push(v);
645                }
646            } else if (view === "tomorrow") { // Tomorrow is between start and end date
647                if (moment().add(1, 'days').isBetween(startDateM, endDateM, 'date', '[]')) {
648                    checkedEvents.push(v);
649                }
650            } else if (view === "this-week") { // Start date is on or before THIS Saturday AND End date is on or after LAST Sunday
651                if (startDateM.isSameOrBefore(moment().weekday(6), "day") && endDateM.isSameOrAfter(moment().weekday(0), "day")) {
652                    checkedEvents.push(v);
653                }
654            } else if (view === "this-weekend") { // Start date is on or before NEXT Sunday AND End date is on or after THIS Friday
655                if (startDateM.isSameOrBefore(moment().weekday(7), "day") && endDateM.isSameOrAfter(moment().weekday(5), "day")) {
656                    checkedEvents.push(v);
657                }
658            } else if (view === "next-week") { // Start date is on or before NEXT Saturday AND End date is on or after NEXT Sunday
659                if (startDateM.isSameOrBefore(moment().weekday(13), "day") && endDateM.isSameOrAfter(moment().weekday(7), "day")) {
660                    checkedEvents.push(v);
661                }
662            } else if (view === "this-month") { // Today's month is between the start and end month
663                if (moment().isBetween(startDateM, endDateM, 'month', '[]')) {
664                    checkedEvents.push(v);
665                }
666            } else if (view === "next-month") { // The month after today's month is between the start and end month
667                if (moment().add(1, 'months').isBetween(startDateM, endDateM, 'month', '[]')) {
668                    checkedEvents.push(v);
669                }
670            } else {
671                if (view === undefined || view == "") {
672                    checkedEvents.push(v);
673                } else { // Date choosers
674                    if (view.indexOf("-") > -1) { // Start date is on or before the selected end date AND end date is on or after the selected start date
675                        if (startDateM.isSameOrBefore(moment(rangeDateEnd, "MM/DD/YYYY"), "day") && endDateM.isSameOrAfter(moment(rangeDateStart, "MM/DD/YYYY"), "day")) {
676                            checkedEvents.push(v);
677                        }
678                    } else { // Selected date is on or between the start and end dates
679                        if (moment(view, "MM/DD/YYYY").isBetween(startDateM, endDateM, 'day', '[]')) {
680                            checkedEvents.push(v);
681                        }
682                    }
683                }
684            }
685        }
686    }
687}
688
689// Pre-end date filter function
690/*function eventDateCheck(v, view) {
691    if (v.startDate != undefined) {
692        var startDateM = moment(v.startDate);
693        if (view === "upcoming-events" || view === "featured" || view === "side-featured-events" || view === "related-events" || view === "current-recurring-event" || view === "hh-events-block") {
694            if (startDateM.isSameOrAfter(moment())) {
695                checkedEvents.push(v);
696            }
697        } else if (view === "today") {
698            if (moment().isSame(startDateM, 'date')) {
699                checkedEvents.push(v);
700            }
701        } else if (view === "tomorrow") {
702            if (moment(moment().add(1, 'days')).isSame(startDateM, 'date')) {
703                checkedEvents.push(v);
704            }
705        } else if (view === "this-week") {
706            if (moment(startDateM).isSameOrAfter(moment().weekday(0), "day") && moment(startDateM).isSameOrBefore(moment().weekday(6), "day")) {
707                checkedEvents.push(v);
708            }
709        } else if (view === "this-weekend") {
710            if (moment(startDateM).isSameOrAfter(moment().weekday(5), "day") && moment(startDateM).isSameOrBefore(moment().weekday(7), "day")) {
711                checkedEvents.push(v);
712            }
713        } else if (view === "next-week") {
714            if (moment(startDateM).isSameOrAfter(moment().weekday(7), "day") && moment(startDateM).isSameOrBefore(moment().weekday(13), "day")) {
715                checkedEvents.push(v);
716            }
717        } else if (view === "this-month") {
718            if (moment().isSame(startDateM, 'month')) {
719                checkedEvents.push(v);
720            }
721        } else if (view === "next-month") {
722            if (moment().add(1, 'months').isSame(startDateM, 'month')) {
723                checkedEvents.push(v);
724            }
725        } else {
726            if (view === undefined || view == "") {
727                checkedEvents.push(v);
728            } else {;
729                if (view.indexOf("-") > -1) {
730                    if (startDateM.isSameOrAfter(moment(rangeDateStart, "MM/DD/YYYY"), 'day') && startDateM.isSameOrBefore(moment(rangeDateEnd, "MM/DD/YYYY"), 'day')) {
731                        checkedEvents.push(v);
732                    }
733                } else {
734                    if (startDateM.isSame(moment(view, "MM/DD/YYYY"), "day")) {
735                        checkedEvents.push(v);
736                    }
737                }
738            }
739        }
740    }
741}*/
742
743function jsonToCurrentData(data, view) {
744    return new Promise(function(resolve, reject) {
745        var jsonToCurrentDataEvents = [];
746        for (let i = 0; i < data.length; i++) {
747            cdEvent = {};
748            cdEvent.id = data[i].id;
749            cdEvent.title = data[i].title;
750            cdEvent.startDate = data[i].startDate;
751            cdEvent.endDate = data[i].endDate;
752            cdEvent.originalStart = data[i].originalStart;
753            cdEvent.originalEnd = data[i].originalEnd;
754            cdEvent.allDay = data[i].allDay;
755            cdEvent.description = data[i].description;
756            cdEvent.recurringEvent = data[i].recurringEvent;
757            cdEvent.tooltip = data[i].tooltip;
758            cdEvent.image = data[i].image;
759            cdEvent.alt = data[i].alt;
760            cdEvent.featured = data[i].featured;
761            if (filter1) {
762                cdEvent.filter1 = data[i].filter1;
763            }
764            if (filter2) {
765                cdEvent.filter2 = data[i].filter2;
766            }
767            if (filter3) {
768                cdEvent.filter3 = data[i].filter3;
769            }
770            if (filter4) {
771                cdEvent.filter4 = data[i].filter4;
772            }
773            if (filter5) {
774                cdEvent.filter5 = data[i].filter5;
775            }
776            if (filter6) {
777                cdEvent.filter6 = data[i].filter6;
778            }
779            if (filter7) {
780                cdEvent.filter7 = data[i].filter7;
781            }
782            if (filter8) {
783                cdEvent.filter8 = data[i].filter8;
784            }
785            if (filter9) {
786                cdEvent.filter9 = data[i].filter9;
787            }
788            if (filter10) {
789                cdEvent.filter10 = data[i].filter10;
790            }
791            cdEvent.url = data[i].url;
792            jsonToCurrentDataEvents.push(cdEvent);
793
794        }
795        resolve({
796            jsonToCurrentDataEvents: jsonToCurrentDataEvents
797        });
798    });
799}
800
801function eventCount() {
802    $eventsMessageContainer.empty();
803    $eventViewCountDisplay.empty();
804    $eventFilterViewCountDisplay.empty();
805    var $eventsList = $(".events-list");
806    var $filterMatch = $eventsList.find(".filter-match");
807    var $allEvents = $eventsList.find(".event");
808    if ($allEvents.length != $filterMatch.length) {
809        $eventViewCountDisplay.html("Loaded <span>" + $allEvents.length + "</span> event(s)");
810        $eventFilterViewCountDisplay.html(", showing <span>" + $filterMatch.length + "</span> that meet your filter/search criteria. ");
811    } else {
812        $eventViewCountDisplay.html("Showing <span>" + $allEvents.length + "</span> event(s). ")
813    }
814    if ($allEvents.length <= 4 || $filterMatch.length <= 4) {
815        $(".events-results2").removeClass("show-hhe").addClass("hide-hhe");
816    } else {
817        $(".events-results2").removeClass("hide-hhe").addClass("show-hhe");
818    }
819}
820
821/* details */
822
823function eventHTML(v, col) {
824    if (col == undefined) {
825        col = 4;
826    }
827    eventItem = '';
828	let divisible = 12/col;
829    eventItem += '<div class="col-sm-6 col-md-' + col + ' event">';
830    eventItem += '<a href="' + v.url + '" target="_parent">';
831    eventItem += imageOutput(v.image, v.startDate);
832    eventItem += '<h3 class="title">';
833    eventItem += v.title;
834    eventItem += '</h3>';
835    eventItem += '</a>';
836    eventItem += '<div class="details">';
837    if (v.featured == "true") {
838        eventItem += '<div class="featured">';
839        eventItem += '<span class="far fa-star" tabindex="0" aria-label="featured event"></span>';
840        eventItem += '</div>';
841        eventItem += separator;
842    }
843    if (v.recurringEvent == "true") {
844        eventItem += '<div class="recurrence">';
845        eventItem += '<span class="fas fa-sync-alt" title="' + v.tooltip + '" data-toggle="tooltip" data-placement="bottom" tabindex="0" aria-label="occurs ' + v.tooltip + '">';
846        eventItem += '</span>';
847        eventItem += '</div>';
848        eventItem += separator;
849    }
850    var timeText = timeOutput(v.startDate, v.endDate, v.allDay, v.originalStart, v.originalEnd);
851    var timeAriaLabel = timeText.replace(/:/g, ' ').replace(/ - /g, ' to ');
852    eventItem += '<div class="time-hh" aria-label="' + timeAriaLabel + '">' + timeText + '</div>';
853    eventItem += separator;
854    eventItem += '<div class="date">' + dateOutput(v.startDate, v.endDate, "", v.allDay) + '</div>';
855    eventItem += '</div>';
856    eventItem += '</div>';
857    return eventItem;
858}
859
860function getRelatedEvents(data) {
861    return new Promise(function(resolve) {
862        for (let i = 0; i < data.length; i++) {
863            eventList += eventHTML(data[i], 4);
864        };
865        resolve({
866            data: data,
867            events: eventList
868        });
869    })
870}
871
872/* event */
873
874function showEvents(data, view, target, showLimit, origin) {
875    getEvents(data, showLimit, origin, view).then(function(results) {
876        if (debugMode) {
877            console.log("showEvents:", view);
878        }
879        // target.empty();
880        // target.append(results.events);
881        target.html(results.events);
882        $('#events-loaded').text("Events loaded.");
883        if (view != "side-featured-events") {
884            if (setFiltersLoad.length > 0) {
885                showFilter(setFiltersLoad, "showEvents")
886            }
887            searchText($("#search-events").val().toLowerCase());
888            eventCount();
889            currentData = [];
890            $loadMoreContainer.removeClass("show-hhe").addClass("hide-hhe");
891            if (showLimit != "all") {
892                currentData = _.drop(results.data, showLimit);
893                if (currentData.length > 0) {
894                    if (debugMode) {
895                        console.log("show loadMore");
896                    }
897                    $loadMoreContainer.removeClass("hide-hhe").addClass("show-hhe");
898                }
899            }
900            if (debugMode) {
901                console.log("------------------------");
902            }
903        } else {
904            updateSidebarAccessibility();
905        }
906    })
907}
908
909function getEvents(data, showLimit, origin, view) {
910    return new Promise(function(resolve, reject) {
911        if (debugMode) {
912            console.log("getEvents");
913        }
914        for (let iE = 0; iE < data.length; iE++) {
915            var eventsListFilterDots = [];
916            var eventsListFilterTexts = [];
917            var filterClasses = [];
918            var filterData = [
919                { name: "f1", data: data[iE].filter1, eList: filter1EventsList}, { name: "f2", data: data[iE].filter2, eList: filter2EventsList }, { name: "f3", data: data[iE].filter3, eList: filter3EventsList }, { name: "f4", data: data[iE].filter4, eList: filter4EventsList }, { name: "f5", data: data[iE].filter5, eList: filter5EventsList }, { name: "f6", data: data[iE].filter6, eList: filter6EventsList }, { name: "f7", data: data[iE].filter7, eList: filter7EventsList }, { name: "f8", data: data[iE].filter8, eList: filter8EventsList }, { name: "f9", data: data[iE].filter9, eList: filter9EventsList }, { name: "f10", data: data[iE].filter10, eList: filter10EventsList }
920            ];
921            for (let iFD = 0; iFD < filterData.length; iFD++) {
922                if (filterData[iFD].data) {
923                    for (let iFDF = 0; iFDF < filterData[iFD].data.length; iFDF++) {
924                        filterClasses.push(filterData[iFD].data[iFDF].replace(/\s/g, "").replace(/&/g, "and").replace(/[^0-9a-z\-]/gi, "").toLowerCase());
925                    }
926                    
927                    for (let iFDF = 0; iFDF < filterData[iFD].data.length; iFDF++) {
928                        if(filterData[iFD].eList == "dots"){
929                            eventsListFilterDots.push({
930                            "name": filterData[iFD].data[iFDF],
931                            "filter": filterData[iFD].name
932                            });
933                        }
934                        
935                    }
936                    for (let iFDF = 0; iFDF < filterData[iFD].data.length; iFDF++) {
937                        if(filterData[iFD].eList == "text"){
938                            eventsListFilterTexts.push(filterData[iFD].data[iFDF]);
939                        }
940                    }
941                }
942            }
943            eventItem = '';
944            eventItem += '<div class="row event filter-match ' + filterClasses.join(' ') + '">';
945            eventItem += '<a href="' + data[iE].url + '" target="_parent">';
946            eventItem += '<div class="col-xs-12 col-sm-4 image">';
947            eventItem += imageOutput(data[iE].image, data[iE].startDate);
948            eventItem += '</div>';
949            eventItem += '<div class="col-xs-12 col-sm-8"><div class="event-details"><div>';
950            eventItem += '<h3 class="title">';
951            eventItem += data[iE].title;
952            eventItem += '</h3>';
953            eventItem += '<div class="details">';
954            if (data[iE].featured === "true") {
955                eventItem += '<div class="featured">';
956                eventItem += '<span class="far fa-star" tabindex="0" aria-label="featured event"></span>';
957                eventItem += '</div>';
958                eventItem += separator;
959            }
960            if (data[iE].recurringEvent === "true") {
961                eventItem += '<div class="recurrence">';
962                eventItem += '<span class="fas fa-sync-alt" title="' + data[iE].tooltip + '" data-toggle="tooltip" data-placement="bottom" tabindex="0" aria-label="occurs ' + data[iE].tooltip + '">';
963                eventItem += '</span>';
964                eventItem += '</div>';
965                eventItem += separator;
966            }
967            var timeText = timeOutput(data[iE].startDate, data[iE].endDate, data[iE].allDay, data[iE].originalStart, data[iE].originalEnd);
968            var timeAriaLabel = timeText.replace(/:/g, ' ').replace(/ - /g, ' to ');
969            eventItem += '<div class="time-hh" aria-label="' + timeAriaLabel + '">' + timeText + '</div>';
970            eventItem += separator;
971            eventItem += '<div class="date">' + dateOutput(data[iE].startDate, data[iE].endDate, "", data[iE].allDay) + '</div>';
972            if (eventsListFilterTexts.length > 0 || eventsListFilterDots.length > 0) {
973                eventItem += separator;
974                if (view != "side-featured-events") {
975                    eventItem += '<span class="sr-only">Categories: </span>';
976                }
977            }
978            if (eventsListFilterTexts.length > 0) {
979                if (eventsListFilterTexts.length > 1) {
980                    eventItem += '<div class="location listFilterText">' + eventsListFilterTexts.join(', ') + '</div>';
981                } else {
982                    eventItem += '<div class="location listFilterText">' + eventsListFilterTexts.join('') + '</div>';
983                }
984            }
985            if (eventsListFilterDots.length > 0) {
986                // console.log(eventsListFilterDots);
987                eventItem += '<div class="categories listFilterDots">';
988                for (let i = 0; i < eventsListFilterDots.length; i++) {
989                    eventItem += '<span class="fas fa-circle dot ' + eventsListFilterDots[i].filter + "-" + eventsListFilterDots[i].name.toLowerCase().replaceAll("&amp;","and").replaceAll("&","and").replaceAll(/[^A-Za-z0-9]/gi, "") + '-color" title="' + eventsListFilterDots[i].name + '" data-toggle="tooltip" data-placement="bottom" tabindex="0" aria-label="' + eventsListFilterDots[i].name + '"></span>';
990                };
991                eventItem += '</div>';
992            }
993            eventItem += '</div>';
994            if (data[iE].description != undefined) {
995                eventItem += '<p class="summary">' + data[iE].description + '</p>';
996            }
997            eventItem += '</div></div></div>';
998            eventItem += '</a>';
999            eventItem += '</div>';
1000            eventList += eventItem;
1001            if (showLimit != "all" && iE == (showLimit - 1)) {
1002                break;
1003            }
1004        }
1005        resolve({
1006            data: data,
1007            events: eventList
1008        });
1009    })
1010}
1011
1012/* filters */
1013
1014$(".loadFilter:checkbox").change(function(e, extra) {
1015    if (e.originalEvent !== undefined || (extra && extra.fromKeyboard)) {
1016        if (debugMode) {
1017            console.log("------------------------");
1018            console.log("applyFilter: " + $(this).val());
1019        }
1020        var thisChecked = $(this).val().replace(/\s/g, "-").replace(/,/g, "").replace(/&/g, "and").replace(/[^0-9a-z\-]/gi, "").toLowerCase();
1021        var hashChecked = $(this).data('hash') + "=";;
1022        loadView(currentLoadedView, "", "all", "filter").then(function(results) {
1023            showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
1024            if (window.location.hash) {
1025                if (!_.includes(window.location.hash, hashChecked)) {
1026                    if (debugMode) {
1027                        console.log("filter add: " + hashChecked + thisChecked);
1028                    }
1029                    getHash(window.location.hash, hashChecked, function() {
1030                        setHash(hashChecked, "add", thisChecked, function() {
1031                            showFilter(setFiltersLoad, "loadView 1")
1032                        });
1033                    });
1034                } else if (_.includes(window.location.hash, hashChecked)) {
1035                    if (_.includes(window.location.hash, thisChecked)) {
1036                        if (debugMode) {
1037                            console.log("filter remove: " + thisChecked + " from " + hashChecked);
1038                        }
1039                        getHash(window.location.hash, hashChecked, function() {
1040                            setHash(hashChecked, "remove", thisChecked, function() {
1041                                showFilter(setFiltersLoad, "loadView 3")
1042                            });
1043                        });
1044                    } else {
1045                        if (debugMode) {
1046                            console.log("filter add: " + thisChecked + " to " + hashChecked);
1047                        }
1048                        getHash(window.location.hash, hashChecked, function() {
1049                            setHash(hashChecked, "add", thisChecked, function() {
1050                                showFilter(setFiltersLoad, "loadView 2")
1051                            });
1052                        });
1053                    }
1054                }
1055            } else {
1056                if (debugMode) {
1057                    console.log("filter add: " + hashChecked + thisChecked);
1058                }
1059                getHash(window.location.hash, hashChecked, function() {
1060                    setHash(hashChecked, "add", thisChecked, function() {
1061                        showFilter(setFiltersLoad, "loadView 1")
1062                    });
1063                });
1064            }
1065        });
1066    }
1067});
1068
1069$("select.loadFilter").change(function(e) {
1070    if (e.originalEvent !== undefined) {
1071        if (debugMode) {
1072            console.log("------------------------");
1073            console.log("applyFilter: " + $(this).val());
1074        }
1075        var thisSelected = $(this).val().replace(/\s/g, "-").replace(/,/g, "").replace(/&/g, "and").replace(/[^0-9a-z\-]/gi, "").toLowerCase();
1076        var selectedHash = $(this).data('hash') + "=";
1077        loadView(currentLoadedView, "", "all", "filter").then(function(results) {
1078            showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
1079            if (_.includes(window.location.hash, selectedHash)) {
1080                if (debugMode) {
1081                    console.log("filter replace " + selectedHash + thisSelected);
1082                }
1083                getHash(window.location.hash, selectedHash, function() {
1084                    setHash(selectedHash, "replace", thisSelected, function() {
1085                        showFilter(setFiltersLoad, "select.loadFilter");
1086                    });
1087                });
1088            } else {
1089                if (debugMode) {
1090                    console.log("filter add " + selectedHash + thisSelected);
1091                }
1092                getHash(window.location.hash, selectedHash, function() {
1093                    setHash(selectedHash, "add", thisSelected, function() {
1094                        showFilter(setFiltersLoad, "select.loadFilter 2");
1095                    });
1096                });
1097 
1097           }
1098        });
1099    };
1100});
1101
1102let searchInput = document.getElementById('search-events');
1103let searchTimeout = null;
1104if(searchInput) {
1105    searchInput.addEventListener('keyup', function(e) {
1106        clearTimeout(searchTimeout);
1107        searchTimeout = setTimeout(function() {
1108            loadView(currentLoadedView, "", "all", "searchText").then(function(results) {
1109                showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
1110                searchText($("#search-events").val().toLowerCase());
1111            });
1112        }, 300);
1113    });
1114}
1115
1116function searchText(textSearch) {
1117    var doesEventContainText = function(eventElement) {
1118        var innerSelectors = ['.title', '.details', '.summary'];
1119        var innerElementMatchesText = function(selector) {
1120            var element = eventElement.querySelector(selector) || {
1121                innerText: ""
1122            };
1123            return element.innerText.toLowerCase().match(textSearch);
1124        };
1125        for (var i = 0; i < innerSelectors.length; i++) {
1126            if (innerElementMatchesText(innerSelectors[i])) {
1127                return true;
1128            }
1129        }
1130        return false;
1131    };
1132    if (debugMode) {
1133        console.log("searchText:", textSearch);
1134    }
1135    if (textSearch.length) {
1136        var $filterMatches = $eventsContainer.find('.filter-match');
1137        for (var i = 0; i < $filterMatches.length; i++) {
1138            var element = $filterMatches[i];
1139            if (!doesEventContainText(element)) {
1140                element.classList.remove("filter-match");
1141            }
1142        }
1143        eventCount();
1144    }
1145}
1146
1147function showFilter(filter, origin) {
1148    if (debugMode) {
1149        console.log("showFilter");
1150        console.log("filter: " + filter);
1151        console.log("origin: " + origin);
1152    }
1153    if (filter.length > 1) {
1154        $eventsContainer.find('.row.event').removeClass("filter-match");
1155        $eventsContainer.find(filter).addClass("filter-match");
1156        eventCount();
1157        checkFilter(filter);
1158    } else {
1159        $eventsContainer.find('.row.event').addClass("filter-match");
1160        eventCount();
1161    }
1162}
1163
1164function checkFilter(filter) {
1165    if (debugMode) {
1166        console.log("checkfilter");
1167        console.log(filter);
1168    }
1169    checkFilters = filter.replace(/, /g, '');
1170    checkFilters = checkFilters.split(".");
1171    checkFilters = _.compact(checkFilters);
1172    if (debugMode) {
1173        console.log(checkFilters);
1174    }
1175    for (let i = 0; i < checkFilters.length; i++) {
1176        $(".loadFilter:checkbox[value=" + checkFilters[i] + "]").prop("checked", "true");
1177    };
1178    for (let i = 0; i < checkFilters.length; i++) {
1179        var selectLoadFilters = document.querySelectorAll('select.loadFilter');
1180        for (iSLF = 0; iSLF < selectLoadFilters.length; ++iSLF) {
1181            for (iSO = 0; iSO < selectLoadFilters[iSLF].options.length; ++iSO) {
1182                if (checkFilters[i] == selectLoadFilters[iSLF].options[iSO].value) {
1183                    selectLoadFilters[iSLF].value = checkFilters[i];
1184                }
1185            };
1186        };
1187    };
1188}
1189
1190/* hash */
1191
1192function newHashF(newHash) {
1193    if (newHash !== window.location.hash) {
1194        removeHash();
1195        history.pushState(null, document.title, window.location.pathname + newHash);
1196    }
1197}
1198
1199function getHash(hash, type, callback) {
1200    vHashes = [];
1201    f1Hashes = [];
1202    f2Hashes = [];
1203    f3Hashes = [];
1204    f4Hashes = [];
1205    f5Hashes = [];
1206    f6Hashes = [];
1207    f7Hashes = [];
1208    f8Hashes = [];
1209    f9Hashes = [];
1210    f10Hashes = [];
1211    if (hash) {
1212        getHashArray = hash + "&";
1213        getHashArray = getHashArray.replace("#", "").split("&");
1214        getHashArray = _.compact(getHashArray);
1215
1216        for (let i = 0; i < getHashArray.length; i++) {
1217            if (_.includes(getHashArray[i], "v=")) {
1218                vHashes.push(getHashArray[i]);
1219            } else if (_.includes(getHashArray[i], "f1=")) {
1220                f1Hashes.push(getHashArray[i]);
1221            } else if (_.includes(getHashArray[i], "f2=")) {
1222                f2Hashes.push(getHashArray[i]);
1223            } else if (_.includes(getHashArray[i], "f3=")) {
1224                f3Hashes.push(getHashArray[i]);
1225            } else if (_.includes(getHashArray[i], "f4=")) {
1226                f4Hashes.push(getHashArray[i]);
1227            } else if (_.includes(getHashArray[i], "f5=")) {
1228                f5Hashes.push(getHashArray[i]);
1229            } else if (_.includes(getHashArray[i], "f6=")) {
1230                f6Hashes.push(getHashArray[i]);
1231            } else if (_.includes(getHashArray[i], "f7=")) {
1232                f7Hashes.push(getHashArray[i]);
1233            } else if (_.includes(getHashArray[i], "f8=")) {
1234                f8Hashes.push(getHashArray[i]);
1235            } else if (_.includes(getHashArray[i], "f9=")) {
1236                f9Hashes.push(getHashArray[i]);
1237            } else if (_.includes(getHashArray[i], "f10=")) {
1238                f10Hashes.push(getHashArray[i]);
1239            }
1240        };
1241    }
1242    if (callback) {
1243        callback();
1244    }
1245}
1246
1247function setHash(type, action, value, callback) {
1248    setViews = "";
1249    setViewsLoad = "";
1250    setFilters = "";
1251    setFiltersClean = "";
1252    setFiltersMerged = "";
1253    setFiltersLoad = "";
1254    if (type === "v=") {
1255        vHashes = [];
1256        vHashes.push(type + value);
1257    } else if (type === "f1=") {
1258        if (_.includes(f1Hashes.toString(), type)) {
1259            if (action === "add") {
1260                f1HashesString = f1Hashes.toString() + "," + value;
1261                f1Hashes = [];
1262                f1Hashes.push(f1HashesString);
1263            } else if (action === "remove") {
1264                f1HashesString = f1Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1265                f1Hashes = [];
1266                if (f1HashesString != "f1=") {
1267                    f1Hashes.push(f1HashesString);
1268                }
1269            } else if (action === "replace") {
1270                f1Hashes = [];
1271                f1HashesString = type + value;
1272                if (f1HashesString != "f1=") {
1273                    f1Hashes.push(f1HashesString);
1274                }
1275            }
1276        } else {
1277            f1Hashes.push(type + value);
1278        }
1279    } else if (type === "f2=") {
1280        if (_.includes(f2Hashes.toString(), type)) {
1281            if (action === "add") {
1282                f2HashesString = f2Hashes.toString() + "," + value;
1283                f2Hashes = [];
1284                f2Hashes.push(f2HashesString);
1285            } else if (action === "remove") {
1286                f2HashesString = f2Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1287                f2Hashes = [];
1288                if (f2HashesString != "f2=") {
1289                    f2Hashes.push(f2HashesString);
1290                }
1291            } else if (action === "replace") {
1292                f2Hashes = [];
1293                f2HashesString = type + value;
1294                if (f2HashesString != "f2=") {
1295                    f2Hashes.push(f2HashesString);
1296                }
1297            }
1298        } else {
1299            f2Hashes.push(type + value);
1300        }
1301    } else if (type === "f3=") {
1302        if (_.includes(f3Hashes.toString(), type)) {
1303            if (action === "add") {
1304                f3HashesString = f3Hashes.toString() + "," + value;
1305                f3Hashes = [];
1306                f3Hashes.push(f3HashesString);
1307            } else if (action === "remove") {
1308                f3HashesString = f3Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1309                f3Hashes = [];
1310                if (f3HashesString != "f3=") {
1311                    f3Hashes.push(f3HashesString);
1312                }
1313            } else if (action === "replace") {
1314                f3Hashes = [];
1315                f3HashesString = type + value;
1316                if (f3HashesString != "f3=") {
1317                    f3Hashes.push(f3HashesString);
1318                }
1319            }
1320        } else {
1321            f3Hashes.push(type + value);
1322        }
1323    } else if (type === "f4=") {
1324        if (_.includes(f4Hashes.toString(), type)) {
1325            if (action === "add") {
1326                f4HashesString = f4Hashes.toString() + "," + value;
1327                f4Hashes = [];
1328                f4Hashes.push(f4HashesString);
1329            } else if (action === "remove") {
1330                f4HashesString = f4Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1331                f4Hashes = [];
1332                if (f4HashesString != "f4=") {
1333                    f4Hashes.push(f4HashesString);
1334                }
1335            } else if (action === "replace") {
1336                f4Hashes = [];
1337                f4HashesString = type + value;
1338                if (f4HashesString != "f4=") {
1339                    f4Hashes.push(f4HashesString);
1340                }
1341            }
1342        } else {
1343            f4Hashes.push(type + value);
1344        }
1345    } else if (type === "f5=") {
1346        if (_.includes(f5Hashes.toString(), type)) {
1347            if (action === "add") {
1348                f5HashesString = f5Hashes.toString() + "," + value;
1349                f5Hashes = [];
1350                f5Hashes.push(f5HashesString);
1351            } else if (action === "remove") {
1352                f5HashesString = f5Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1353                f5Hashes = [];
1354                if (f5HashesString != "f5=") {
1355                    f5Hashes.push(f5HashesString);
1356                }
1357            } else if (action === "replace") {
1358                f5Hashes = [];
1359                f5HashesString = type + value;
1360                if (f5HashesString != "f5=") {
1361                    f5Hashes.push(f5HashesString);
1362                }
1363            }
1364        } else {
1365            f5Hashes.push(type + value);
1366        }
1367    } else if (type === "f6=") {
1368        if (_.includes(f6Hashes.toString(), type)) {
1369            if (action === "add") {
1370                f6HashesString = f6Hashes.toString() + "," + value;
1371                f6Hashes = [];
1372                f6Hashes.push(f6HashesString);
1373            } else if (action === "remove") {
1374                f6HashesString = f6Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1375                f6Hashes = [];
1376                if (f6HashesString != "f6=") {
1377                    f6Hashes.push(f6HashesString);
1378                }
1379            } else if (action === "replace") {
1380                f6Hashes = [];
1381                f6HashesString = type + value;
1382                if (f6HashesString != "f6=") {
1383                    f6Hashes.push(f6HashesString);
1384                }
1385            }
1386        } else {
1387            f6Hashes.push(type + value);
1388        }
1389    } else if (type === "f7=") {
1390        if (_.includes(f7Hashes.toString(), type)) {
1391            if (action === "add") {
1392                f7HashesString = f7Hashes.toString() + "," + value;
1393                f7Hashes = [];
1394                f7Hashes.push(f7HashesString);
1395            } else if (action === "remove") {
1396                f7HashesString = f7Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1397                f7Hashes = [];
1398                if (f7HashesString != "f7=") {
1399                    f7Hashes.push(f7HashesString);
1400                }
1401            } else if (action === "replace") {
1402                f7Hashes = [];
1403                f7HashesString = type + value;
1404                if (f7HashesString != "f7=") {
1405                    f7Hashes.push(f7HashesString);
1406                }
1407            }
1408        } else {
1409            f7Hashes.push(type + value);
1410        }
1411    } else if (type === "f8=") {
1412        if (_.includes(f8Hashes.toString(), type)) {
1413            if (action === "add") {
1414                f8HashesString = f8Hashes.toString() + "," + value;
1415                f8Hashes = [];
1416                f8Hashes.push(f8HashesString);
1417            } else if (action === "remove") {
1418                f8HashesString = f8Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1419                f8Hashes = [];
1420                if (f8HashesString != "f8=") {
1421                    f8Hashes.push(f8HashesString);
1422                }
1423            } else if (action === "replace") {
1424                f8Hashes = [];
1425                f8HashesString = type + value;
1426                if (f8HashesString != "f8=") {
1427                    f8Hashes.push(f8HashesString);
1428                }
1429            }
1430        } else {
1431            f8Hashes.push(type + value);
1432        }
1433    } else if (type === "f9=") {
1434        if (_.includes(f9Hashes.toString(), type)) {
1435            if (action === "add") {
1436                f9HashesString = f9Hashes.toString() + "," + value;
1437                f9Hashes = [];
1438                f9Hashes.push(f9HashesString);
1439            } else if (action === "remove") {
1440                f9HashesString = f9Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1441                f9Hashes = [];
1442                if (f9HashesString != "f9=") {
1443                    f9Hashes.push(f9HashesString);
1444                }
1445            } else if (action === "replace") {
1446                f9Hashes = [];
1447                f9HashesString = type + value;
1448                if (f9HashesString != "f9=") {
1449                    f9Hashes.push(f9HashesString);
1450                }
1451            }
1452        } else {
1453            f9Hashes.push(type + value);
1454        }
1455    } else if (type === "f10=") {
1456        if (_.includes(f10Hashes.toString(), type)) {
1457            if (action === "add") {
1458                f10HashesString = f10Hashes.toString() + "," + value;
1459                f10Hashes = [];
1460                f10Hashes.push(f10HashesString);
1461            } else if (action === "remove") {
1462                f10HashesString = f10Hashes.toString().replace("," + value, "").replace(value + ",", "").replace(value, "");
1463                f10Hashes = [];
1464                if (f10HashesString != "f10=") {
1465                    f10Hashes.push(f10HashesString);
1466                }
1467            } else if (action === "replace") {
1468                f10Hashes = [];
1469                f10HashesString = type + value;
1470                if (f10HashesString != "f10=") {
1471                    f10Hashes.push(f10HashesString);
1472                }
1473            }
1474        } else {
1475            f10Hashes.push(type + value);
1476        }
1477    }
1478    setViews = vHashes.join();
1479    setViewsLoad = setViews.replace("v=", "");
1480    setFiltersMerged = "";
1481    setFilters = _.concat(f1Hashes, f2Hashes, f3Hashes, f4Hashes, f5Hashes, f6Hashes, f7Hashes, f8Hashes, f9Hashes, f10Hashes);
1482    setFiltersClean = _.compact(setFilters);
1483    setFiltersMerged = "&" + setFiltersClean.join("&");
1484    setFiltersLoad = setFiltersMerged;
1485    for (let i = 0; i < urlHashes.length; i++) {
1486        setFiltersLoad = setFiltersLoad.replace(urlHashes[i], "");
1487    };
1488    setFiltersLoad = setFiltersLoad.substring(1);
1489    setFiltersLoad = "." + setFiltersLoad;
1490    setFiltersLoad = setFiltersLoad.replace(/&/g, filterLogic).replace(/=/g, ".").replace(/,/g, filterLogic).replace(/\.\./g, ".").replace(/\. \./g, ".");
1491    if (debugMode) {
1492        console.log("------------------------");
1493        console.log({
1494            setViews
1495        });
1496        console.log({
1497            setViewsLoad
1498        });
1499        console.log({
1500            setFilters
1501        });
1502        console.log({
1503            setFiltersClean
1504        });
1505        console.log({
1506            setFiltersMerged
1507        });
1508        console.log({
1509            urlHashes
1510        });
1511        console.log({
1512            setFiltersLoad
1513        });
1514    }
1515    if (setFiltersLoad === ".") {
1516        setFiltersLoad = "";
1517    }
1518    if (setFiltersClean.length > 0) {
1519        if (setViews.length > 0) {
1520            setURLHash = "#" + setViews + setFiltersMerged;
1521        } else {
1522            setURLHash = "#" + setFiltersMerged.substring(1);
1523        }
1524    } else {
1525        setURLHash = "#" + setViews
1526    }
1527    if (setURLHash === "#") {
1528        newHashF("");
1529    } else {
1530        newHashF(setURLHash);
1531    }
1532    if (callback) {
1533        callback();
1534    }
1535}
1536
1537function removeHash(callback) {
1538    history.pushState("", document.title, window.location.pathname + window.location.search);
1539    if (callback) {
1540        callback();
1541    }
1542}
1543
1544/* recurring */
1545
1546function calculateRecurrences(data) {
1547    if (debugMode) {
1548        console.log({
1549            "recurDataIn": data
1550        });
1551    }
1552    return new Promise(function(resolve, reject) {
1553        var recurringData = [];
1554        var daysArray = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
1555        var fullDayArray = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
1556        for (let i = 0; i < data.length; i++) {
1557            // console.log(data[i]);
1558            if (data[i] != undefined && data[i].recurringEvent === "true") { /* Get the date data */
1559                var startMoment = moment.parseZone(data[i].startDate);
1560                var _startMoment = startMoment.clone();
1561                var endMoment = moment.parseZone(data[i].endDate);
1562                var difference = endMoment.diff(startMoment);
1563                var untilMoment = moment.parseZone(data[i].recurringDetails.recurUntilDate); /* Get cancellations of recurring event */
1564                var cancellations = [];
1565                for (let iC = 0; iC < data[i].recurringDetails.recurCancellations.length; iC++) {
1566                    cancellations.push(data[i].recurringDetails.recurCancellations[iC])
1567                }; /* Calculate the recurring events */
1568                if (data[i].recurringDetails.recurFrequency === "daily") {
1569                    if (data[i].recurringDetails.recurInterval > 1) {
1570                        data[i].tooltip = "Every " + data[i].recurringDetails.recurInterval + " days";
1571                    } else {
1572                        data[i].tooltip = "Daily";
1573                    }
1574                    while (untilMoment.diff(startMoment, "s") >= 0) { /* Add the current event */
1575                        var thisRecurrence = $.extend({}, data[i]);
1576                        thisRecurrence.startDate = startMoment.valueOf();
1577                        thisRecurrence.endDate = endMoment.valueOf();
1578                        if (!checkCancellations(cancellations, thisRecurrence.startDate)) {
1579                            recurringData.push(thisRecurrence);
1580                        } /* Increment by X days */
1581                        startMoment.add(data[i].recurringDetails.recurInterval, "days").valueOf();
1582                        endMoment.add(data[i].recurringDetails.recurInterval, "days").valueOf();
1583                    }
1584                } else if (data[i].recurringDetails.recurFrequency === "weekly") {
1585                    if (data[i].recurringDetails.recurInterval > 1) {
1586                        data[i].tooltip = "Every " + data[i].recurringDetails.recurInterval + " weeks";
1587                    } else {
1588                        data[i].tooltip = "Weekly";
1589                    }
1590                    var untilMomentRecurs = untilMoment.clone().add(data[i].recurringDetails.recurInterval, "weeks"); /* Incase event stops recurring during the week it still has events */
1591                    if (data[i].recurringDetails.recurDays != undefined && data[i].recurringDetails.recurDays.length > 0) {
1592                        data[i].tooltip += " on ";
1593                        for (var day = 0; day < data[i].recurringDetails.recurDays.length; day++) {
1594                            data[i].tooltip += data[i].recurringDetails.recurDays[day];
1595                            if (day < data[i].recurringDetails.recurDays.length - 2) {
1596                                data[i].tooltip += ", ";
1597                            }
1598                            if (day == data[i].recurringDetails.recurDays.length - 2) {
1599                                data[i].tooltip += " & ";
1600                            }
1601                        }
1602                        while (untilMomentRecurs.diff(startMoment, "s") >= 0) { /* Loop over the selected days of the week */
1603                            for (var day = 0; day < data[i].recurringDetails.recurDays.length; day++) {
1604                                var thisDay = data[i].recurringDetails.recurDays[day];
1605                                startMoment.date(startMoment.date() + (daysArray.indexOf(thisDay) - startMoment.day()));
1606                                endMoment = startMoment.clone().add(difference, "ms"); /* Only add occurrences that are after the actual start date & before the actual until date */
1607                                if (startMoment.diff(_startMoment, "s") >= 0 && startMoment.diff(untilMoment, "s") <= 0) {
1608                                    var thisRecurrence = $.extend({}, data[i]);
1609                                    thisRecurrence.startDate = startMoment.valueOf();
1610                                    thisRecurrence.endDate = endMoment.valueOf();
1611                                    if (!checkCancellations(cancellations, thisRecurrence.startDate)) {
1612                                        recurringData.push(thisRecurrence);
1613                                    }
1614                                }
1615                            } /* Increment by X weeks */
1616                            startMoment.add(data[i].recurringDetails.recurInterval, "weeks");
1617                            endMoment.add(data[i].recurringDetails.recurInterval, "weeks");
1618                        }
1619                    } else {
1620                        while (untilMomentRecurs.diff(startMoment, "s") >= 0) { /* Add the current event */ /* Only add occurrences that are before the actual until date */
1621                            if (startMoment.diff(untilMoment, "s") <= 0) {
1622                                var thisRecurrence = $.extend({}, data[i]);
1623                                thisRecurrence.startDate = startMoment.valueOf();
1624                                thisRecurrence.endDate = endMoment.valueOf();
1625                                if (!checkCancellations(cancellations, thisRecurrence.startDate)) {
1626                                    recurringData.push(thisRecurrence);
1627                                }
1628                            } /* Increment by X weeks */
1629                            startMoment.add(data[i].recurringDetails.recurInterval, "weeks").valueOf();
1630                            endMoment.add(data[i].recurringDetails.recurInterval, "weeks").valueOf();
1631                        }
1632                    }
1633                } else if (data[i].recurringDetails.recurFrequency === "monthly") {
1634                    if (data[i].recurringDetails.recurInterval > 1) {
1635                        data[i].tooltip = "Every " + data[i].recurringDetails.recurInterval + " months";
1636                    } else {
1637                        data[i].tooltip = "Monthly";
1638                    }
1639                    if (data[i].recurringDetails.recurMonth === "day of the month") { /* The same day of the month on each month (1st, 2nd, etc) */
1640                        data[i].tooltip += " on the " + startMoment.format('Do') + " day";
1641                        while (untilMoment.diff(startMoment, "s") >= 0) { /* Ensure the date exists within the current month */
1642                            if (startMoment.date() == _startMoment.date()) {
1643                                var thisRecurrence = $.extend({}, data[i]);
1644                                thisRecurrence.startDate = startMoment.valueOf();
1645                                thisRecurrence.endDate = endMoment.valueOf();
1646                                if (!checkCancellations(cancellations, thisRecurrence.startDate)) {
1647                                    recurringData.push(thisRecurrence);
1648                                }
1649                            } /* Increment by X months */
1650                            startMoment.add(data[i].recurringDetails.recurInterval, "months");
1651                            if (startMoment.daysInMonth() >= _startMoment.date()) {
1652                                startMoment.date(_startMoment.date());
1653                            }
1654                            endMoment = startMoment.clone().add(difference, "ms");
1655                        }
1656                    } else if (data[i].recurringDetails.recurMonth === "day of the week") { /* The same day of the week of the month (2nd Tues of month) */
1657                        data[i].tooltip += " on the " + nth(Math.ceil(startMoment.date() / 7)) + " " + fullDayArray[startMoment.day()]; /* Add a monthly occurrence based on the original event's day of the week */ /* Determine the position of this day in the month (ie 1st, 2nd ...) */
1658                        var theWeek = Math.floor(startMoment.date() / 7),
1659                            theDay = startMoment.day() + 1,
1660                            tempMonth = startMoment.month();
1661                        while (untilMoment.diff(startMoment, "s") >= 0) { /* If we didn't roll over into the next month, add the event */
1662                            if (tempMonth === startMoment.month()) {
1663                                var thisRecurrence = $.extend({}, data[i]);
1664                                thisRecurrence.startDate = startMoment.valueOf();
1665                                thisRecurrence.endDate = endMoment.valueOf();
1666                                if (!checkCancellations(cancellations, thisRecurrence.startDate)) {
1667                                    recurringData.push(thisRecurrence);
1668                                }
1669                            } /* Figure out where the next month's first day lies and add the difference in days with the weekly position */
1670                            startMoment.add(data[i].recurringDetails.recurInterval, "months").date(1);
1671                            tempMonth = startMoment.month();
1672                            if (theDay <= startMoment.day()) {
1673                                startMoment.date((theDay - startMoment.day() + ((theWeek + 1) * 7)));
1674                            } else {
1675                                startMoment.date((theDay - startMoment.day() + (theWeek * 7)));
1676                            }
1677                            endMoment = startMoment.clone().add(difference, "ms");
1678                        }
1679                    }
1680                } else if (data[i].recurringDetails.recurFrequency === "yearly") {
1681                    if (data[i].recurringDetails.recurInterval > 1) {
1682                        data[i].tooltip = "Every " + data[i].recurringDetails.recurInterval + " years";
1683                    } else {
1684                        data[i].tooltip = "Yearly";
1685                    }
1686                    while (untilMoment.diff(startMoment, "s") >= 0) { /* Add the current event */
1687                        var thisRecurrence = $.extend({}, data[i]);
1688                        thisRecurrence.startDate = startMoment.valueOf();
1689                        thisRecurrence.endDate = endMoment.valueOf();
1690                        if (!checkCancellations(cancellations, thisRecurrence.startDate)) {
1691                            recurringData.push(thisRecurrence);
1692                        } /* Increment by X years */
1693                        startMoment.add(data[i].recurringDetails.recurInterval, "years").valueOf();
1694                        endMoment.add(data[i].recurringDetails.recurInterval, "years").valueOf();
1695                    }
1696                }
1697            }
1698        };
1699        if (debugMode) {
1700            console.log({
1701                "recurDataOut": recurringData
1702            });
1703        }
1704        resolve(recurringData);
1705    })
1706}
1707
1708function checkCancellations(cancellations, checkDate) {
1709    var cancelled = false;
1710    if (cancellations.length > 0) {
1711        for (let i = 0; i < cancellations.length; i++) {
1712            cancelled = moment.parseZone(checkDate).isSame(cancellations[i], 'day');
1713            if (cancelled) {
1714                break;
1715            }
1716        };
1717    }
1718    return cancelled;
1719}
1720
1721function nth(n) {
1722    return n + ["st", "nd", "rd"][((n + 90) % 100 - 10) % 10 - 1] || "th"
1723}
1724
1725function recurringURLs(view) {
1726    if (debugMode) {
1727        console.log("recurringData");
1728    }
1729    return new Promise(function(resolve, reject) {
1730        viewChecker(view).then(function(results) {
1731            resolve(results);
1732        });
1733    })
1734}
1735
1736/* view */
1737
1738$(".loadView").on("click", function() {
1739    if (debugMode) {
1740        console.log("------------------------");
1741        console.log("clicked: " + $(this).text());
1742    }
1743    $(this).blur();
1744    $('.input-daterange input').datepicker('update', null);
1745    $('.input-daterange').datepicker('updateDates');
1746    clickedView = $(this).text().replace(/All /gi, "").replace(/\s/g, "-").replace(/,/g, "").replace(/&/g, "and").replace(/[^0-9a-z\-]/gi, "").toLowerCase();
1747    getHash(window.location.hash, "", function() {
1748        setHash("v=", "replace", clickedView, function() {
1749            loadView(clickedView).then(function(results) {
1750                showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
1751            });
1752        });
1753    });
1754});
1755
1756function loadView(view, target, showLimit, origin) {
1757    return new Promise(function(resolve, reject) {
1758        if (debugMode) {
1759            console.log("loadView: " + view);
1760        }
1761        if (target === undefined || target == "") {
1762            target = $eventsContainer;
1763        }
1764        if (showLimit === undefined || showLimit == "") {
1765            showLimit = defaultViewCount;
1766        }
1767        if (view != "side-featured-events") {
1768            currentLoadedView = view;
1769        }
1770        eventList = "";
1771        // currentDataURLs = []; // weirdly fixes date range issue
1772        viewChecker(view).then(function(results) {
1773            if (view === "upcoming-events") {
1774                $eventViewHeader.html("Upcoming Events");
1775                checkDataURLs(results, view, target, showLimit, origin).then(function(results) {
1776                    resolve({
1777                        "events": results.events,
1778                        "view": results.view,
1779                        "target": results.target,
1780                        "showLimit": results.showLimit,
1781                        "origin": results.origin
1782                    });
1783                });
1784            } else if (view === "this-month") {
1785                $eventViewHeader.html("This Month's Events");
1786                checkDataURLs(results, view, target, "all").then(function(results) {
1787                    resolve({
1788                        "events": results.events,
1789                        "view": results.view,
1790                        "target": results.target,
1791                        "showLimit": results.showLimit,
1792                        "origin": results.origin
1793                    });
1794                });
1795            } else if (view === "today") {
1796                $eventViewHeader.html("Today's Events");
1797                checkDataURLs(results, view, target, "all").then(function(results) {
1798                    resolve({
1799                        "events": results.events,
1800                        "view": results.view,
1801                        "target": results.target,
1802                        "showLimit": results.showLimit,
1803                        "origin": results.origin
1804                    });
1805                });
1806            } else if (view === "tomorrow") {
1807                $eventViewHeader.html("Tomorrow's Events");
1808                checkDataURLs(results, view, target, "all").then(function(results) {
1809                    resolve({
1810                        "events": results.events,
1811                        "view": results.view,
1812                        "target": results.target,
1813                        "showLimit": results.showLimit,
1814                        "origin": results.origin
1815                    });
1816                });
1817            } else if (view === "this-week") {
1818                $eventViewHeader.html("This Week's Events");
1819                checkDataURLs(results, view, target, "all").then(function(results) {
1820                    resolve({
1821                        "events": results.events,
1822                        "view": results.view,
1823                        "target": results.target,
1824                        "showLimit": results.showLimit,
1825                        "origin": results.origin
1826                    });
1827                });
1828            } else if (view === "this-weekend") {
1829                $eventViewHeader.html("This Weekend's Events");
1830                checkDataURLs(results, view, target, "all").then(function(results) {
1831                    resolve({
1832                        "events": results.events,
1833                        "view": results.view,
1834                        "target": results.target,
1835                        "showLimit": results.showLimit,
1836                        "origin": results.origin
1837                    });
1838                });
1839            } else if (view === "next-week") {
1840                $eventViewHeader.html("Next Week's Events");
1841                checkDataURLs(results, view, target, "all").then(function(results) {
1842                    resolve({
1843                        "events": results.events,
1844                        "view": results.view,
1845                        "target": results.target,
1846                        "showLimit": results.showLimit,
1847                        "origin": results.origin
1848                    });
1849                });
1850            } else if (view === "this-month") {
1851                $eventViewHeader.html("This Month's Events");
1852                checkDataURLs(results, view, target, "all").then(function(results) {
1853                    resolve({
1854                        "events": results.events,
1855                        "view": results.view,
1856                        "target": results.target,
1857                        "showLimit": results.showLimit,
1858                        "origin": results.origin
1859                    });
1860                });
1861            } else if (view === "next-month") {
1862                $eventViewHeader.html("Next Month's Events");
1863                checkDataURLs(results, view, target, "all").then(function(results) {
1864                    resolve({
1865                        "events": results.events,
1866                        "view": results.view,
1867                        "target": results.target,
1868                        "showLimit": results.showLimit,
1869                        "origin": results.origin
1870                    });
1871                });
1872            } else if (view === "featured" || view === "featured-events") {
1873                view = "featured";
1874                $eventViewHeader.html("Upcoming Featured Events");
1875                checkDataURLs(results, view, target, showLimit, origin).then(function(results) {
1876                    resolve({
1877                        "events": results.events,
1878                        "view": results.view,
1879                        "target": results.target,
1880                        "showLimit": results.showLimit,
1881                        "origin": results.origin
1882                    });
1883                });
1884            } else if (view === "side-featured-events") {
1885                checkDataURLs(results, view, target, showLimit, origin).then(function(results) {
1886                    resolve({
1887                        "events": results.events,
1888                        "view": results.view,
1889                        "target": results.target,
1890                        "showLimit": results.showLimit,
1891                        "origin": results.origin
1892                    });
1893                });
1894            } else {
1895                $eventViewHeader.html(view);
1896                checkDataURLs(results, view, target, "all").then(function(results) {
1897                    resolve({
1898                        "events": results.events,
1899                        "view": results.view,
1900                        "target": results.target,
1901                        "showLimit": results.showLimit,
1902                        "origin": results.origin
1903                    });
1904                });
1905            }
1906        });
1907    })
1908}
1909
1910function viewChecker(view) {
1911    return new Promise(function(resolve, reject) {
1912        var currentDataUrlsViews = ["upcoming-events", "this-month", "today", "tomorrow", "this-week", "this-weekend", "next-week", "this-month", "next-month", "featured", "side-featured-events"];
1913        var pushToCurrentDataURLsIfRangeApplies = function(yearRange, monthRange) {
1914            if (currentYear === yearRange && monthRange >= previousMonth) {
1915                currentDataURLs.push(currentDataURL.replace(/&amp;/g, '&'));
1916            } else {
1917                for (let i = 0; i < dataFiles.length; i++) {
1918                    if (dataFiles[i].name === yearRange + "") {
1919                        currentDataURLs.push(dataFiles[i].link.replace(/&amp;/g, '&'));
1920                    }
1921                };
1922            }
1923        };
1924        if (currentDataUrlsViews.includes(view)) {
1925            currentDataURLs.push(currentDataURL.replace(/&amp;/g, '&'));
1926        } else {
1927            if (view.indexOf("-") > -1) {
1928                rangeDates = [];
1929                rangeDateStart = "";
1930                rangeDateEnd = "";
1931                startYearRange = "";
1932                endYearRange = "";
1933                startMonthRange = "";
1934                endMonthRange = "";
1935                startDayRange = "";
1936                endDayRange = "";
1937                rangeDates = view.split("-");
1938                rangeDateStart = rangeDates[0];
1939                rangeDateEnd = rangeDates[1];
1940                var rangeDateStartM = moment(rangeDateStart, "MM/DD/YYYY", true);
1941                var rangeDateEndM = moment(rangeDateEnd, "MM/DD/YYYY", true);
1942                if (!rangeDateStartM.isValid() && !moment(rangeDateEnd, "MM/DD/YYYY", true).isValid()) {
1943                    eventsMessage = rangeDateStart + "-" + rangeDateStart + " is not a valid date range.";
1944                    errorMessage = true;
1945                } else {
1946                    if (!rangeDateStartM.isValid()) {
1947                        eventsMessage = rangeDateStart + " is not a valid start date.";
1948                        errorMessage = true;
1949                    }
1950                    if (!rangeDateEndM) {
1951                        eventsMessage = rangeDateEnd + " is not a valid end date.";
1952                        errorMessage = true;
1953                    }
1954                }
1955                if (errorMessage) {
1956                    $eventsMessageContainer.html('<p>' + eventsMessage + '</p>').removeClass("hide-hhe").addClass("show-hhe");
1957                } else {
1958                    $eventsMessageContainer.removeClass("show-hhe").addClass("hide-hhe").empty();
1959                    startYearRange = rangeDateStartM.year();
1960                    endYearRange = rangeDateEndM.year();
1961                    startMonthRange = rangeDateStartM.month();
1962                    endMonthRange = rangeDateEndM.month();
1963                    startDayRange = rangeDateStartM.date();
1964                    endDayRange = rangeDateEndM.date();
1965                    if (startYearRange === endYearRange) {
1966                        if (startMonthRange === endMonthRange) {
1967                            pushToCurrentDataURLsIfRangeApplies(startYearRange, startMonthRange);
1968                        } else {
1969                            pushToCurrentDataURLsIfRangeApplies(startYearRange, startMonthRange);
1970                            pushToCurrentDataURLsIfRangeApplies(endYearRange, endMonthRange);
1971                        }
1972                    } else {
1973                        if (currentYear === startYearRange && startMonthRange >= previousMonth) {
1974                            currentDataURLs.push(currentDataURL.replace(/&amp;/g, '&'));
1975                        } else {
1976                            for (i = startYearRange; i <= endYearRange; ++i) {
1977                                for (let iDF = 0; iDF < dataFiles.length; iDF++) {
1978                                    if (dataFiles[iDF].name == i + "") {
1979                                        currentDataURLs.push(dataFiles[iDF].link.replace(/&amp;/g, '&'));
1980                                    }
1981                                };
1982                            }
1983                        }
1984                    }
1985                }
1986            } else {
1987                singleDateYear = "";
1988                singleDateMonth = "";
1989                singleDateDay = "";
1990                singleDate = "";
1991                var viewDateM = moment(view, "MM/DD/YYYY", true);
1992                if (!viewDateM.isValid()) {
1993                    errorMessage = true;
1994                    eventsMessage = '"' + view + '"' + " is not a valid view.";
1995                    $eventsMessageContainer.html(eventsMessage).removeClass("hide-hhe").addClass("show-hhe");
1996                } else {
1997                    $eventsMessageContainer.removeClass("show-hhe").addClass("hide-hhe").empty();
1998                }
1999                if (!errorMessage) {
2000                    singleDate = viewDateM.format('MM/DD/YYYY');
2001                    singleDateYear = viewDateM.year();
2002                    singleDateMonth = viewDateM.month();
2003                    singleDateDay = viewDateM.date();
2004                    pushToCurrentDataURLsIfRangeApplies(singleDateYear, singleDateMonth);
2005                }
2006            }
2007        }
2008        if (debugMode) {
2009            console.log(currentDataURLs);
2010        }
2011        resolve(currentDataURLs);
2012    })
2013}
2014
2015function awaitAll(list, asyncFn) {
2016    const promises = [];
2017    for (let i = 0; i < list.length; i++) {
2018        promises.push(asyncFn(list[i]));
2019    };
2020    return Promise.all(promises);
2021}
2022
2023function urlText(s, preserveCR) {
2024    preserveCR = preserveCR ? '&#13;' : '\n';
2025    return ('' + s).replace(/%/g, '%25').replace(/&amp;/g, '%26').replace(/&/g, '%26').replace(/'/g, '%27').replace(/"/g, '%22').replace(/</g, '%20').replace(/>/g, '%3E').replace(/#/g, '%23').replace(/ /g, '%20').replace(/\r\n/g, preserveCR).replace(/[\r\n]/g, preserveCR);
2026}
2027
2028function saveLinkOutput(title, description, startDate, endDate, timezone, allDay, calendar) {
2029    var startDateO = moment(startDate);
2030    var endDateO = moment(endDate);
2031    if (allDay == "true") {
2032        var ssd = startDateO.format('YYYYMMDD');
2033        var sed = endDateO.add(1, "days").format('YYYYMMDD');
2034        if (calendar == "outlook") {
2035            var ssd = startDateO.format('YYYY-MM-DD');
2036            var sed = endDateO.add(1, "days").format('YYYY-MM-DD');
2037        }
2038    } else {
2039        var ssd = startDateO.format('YYYYMMDDTHHmmZ');
2040        var sed = endDateO.format('YYYYMMDDTHHmmZ');
2041        if (calendar == "outlook") {
2042            var ssd = startDateO.format('YYYY-MM-DDTHH:mmZ');
2043            var sed = endDateO.add(1, "days").format('YYYY-MM-DDTHH:mmZ');
2044        }
2045    }
2046    var saveLinkOutput = "";
2047    if (calendar == "google") {
2048        saveLinkOutput += "<a href='https://calendar.google.com/calendar/r/eventedit?text=" + urlText(title) + "&amp;dates=" + ssd + "/" + sed + "&amp;details=" + urlText(description) + " ' target='_blank'>";
2049        saveLinkOutput += "<span class='fab fa-google' aria-hidden='true'></span> <span class='sr-only'>Add to</span>Google</a>";
2050    } else if (calendar == "outlook") {
2051        saveLinkOutput += "<a target='_blank' href='https://outlook.live.com/owa/?path=/calendar/action/compose&amp;startdt=" + ssd + "&amp;enddt=" + sed + "&amp;subject=" + urlText(title) + "&amp;body=" + urlText(description) + "&amp;allday=" + allDay + " ' target='_blank'>";
2052        saveLinkOutput += "<span class='fab fa-windows' aria-hidden='true'></span> <span class='sr-only'>Add to</span>Outlook</a>";
2053    } else if (calendar == "yahoo") {
2054        if (allDay == "true") {
2055            saveLinkOutput += "<a href='https://calendar.yahoo.com/?v=60&amp;view=d&amp;type=20&amp;title=" + urlText(title) + "&amp;st=" + ssd + "&amp;et=" + sed + "&amp;desc=" + urlText(description) + "&amp;dur=allday' target='_blank'>";
2056        } else {
2057            saveLinkOutput += "<a href='https://calendar.yahoo.com/?v=60&amp;view=d&amp;type=20&amp;title=" + urlText(title) + "&amp;st=" + ssd + "&amp;et=" + sed + "&amp;desc=" + urlText(description) + "' target='_blank'>";
2058        }
2059        saveLinkOutput += "<span class='fab fa-yahoo' aria-hidden='true'></span> <span class='sr-only'>Add to</span>Yahoo</a>";
2060    } else if (calendar == "ics") {
2061        saveLinkOutput += "<a href='" + thisCurrentEvent[0].ics + "' target='_blank'><span class='far fa-calendar-plus' aria-hidden='true'></span> <span class='sr-only'>Download as</span>iCal</a>";
2062    }
2063    return saveLinkOutput;
2064}
2065
2066function currentRecurringEvent() {
2067    calculateRecurrences(thisCurrentEvent).then(function(resultsR) {
2068        eventDateChecker("", resultsR, "current-recurring-event").then(function(results) {
2069            jsonToCurrentData(results).then(function(results) {
2070                var rJCDE = results.jsonToCurrentDataEvents;
2071                if (rJCDE.length > 0) {
2072                    rJCDE.sort(function(a, b) {
2073                        return +new Date(a.startDate) - +new Date(b.startDate);
2074                    });
2075
2076                    for (let i = 0; i < rJCDE.length; i++) {
2077                        $('.rDate').append("Next Occurrence:<br/>" + dateOutput(rJCDE[i].startDate, rJCDE[i].endDate, "full", rJCDE[i].allDay));
2078                        $('#rDates').append('<option selected="selected" value="' + dateOutput(rJCDE[i].startDate, rJCDE[i].endDate, "full", rJCDE[i].allDay) + '" data-title="' + rJCDE[i].title + '" data-desc="' + rJCDE[i].description + '" data-start="' + rJCDE[i].startDate + '" data-end="' + rJCDE[i].endDate + '" data-timezone="' + thisCurrentEvent[0].timezone + '" data-allDay="' + rJCDE[i].allDay + '">' + dateOutput(rJCDE[i].startDate, rJCDE[i].endDate, "full", rJCDE[i].allDay) + '</option>');
2079                        $(".save-row .feeds").append(saveLinkOutput(rJCDE[i].title, rJCDE[i].description, rJCDE[i].startDate, rJCDE[i].endDate, thisCurrentEvent[0].timezone, rJCDE[i].allDay, "google"));
2080                        $(".save-row .feeds").append(saveLinkOutput(rJCDE[i].title, rJCDE[i].description, rJCDE[i].startDate, rJCDE[i].endDate, thisCurrentEvent[0].timezone, rJCDE[i].allDay, "outlook"));
2081                        $(".save-row .feeds").append(saveLinkOutput(rJCDE[i].title, rJCDE[i].description, rJCDE[i].startDate, rJCDE[i].endDate, thisCurrentEvent[0].timezone, rJCDE[i].allDay, "yahoo"));
2082                        $(".save-row .feeds").append(saveLinkOutput(rJCDE[i].title, rJCDE[i].description, rJCDE[i].startDate, rJCDE[i].endDate, thisCurrentEvent[0].timezone, rJCDE[i].allDay, "ics"));
2083                        if (i == 0) {
2084                            break;
2085                        }
2086                    };
2087                    for (let i = 0; i < rJCDE.length; i++) {
2088                        if (i > 0) {
2089                            $('#rDates').append('<option value="' + dateOutput(rJCDE[i].startDate, rJCDE[i].endDate, "full", rJCDE[i].allDay) + '" data-title="' + rJCDE[i].title + '" data-desc="' + rJCDE[i].description + '" data-start="' + rJCDE[i].startDate + '" data-end="' + rJCDE[i].endDate + '" data-timezone="' + thisCurrentEvent[0].timezone + '" data-allDay="' + rJCDE[i].allDay + '">' + dateOutput(rJCDE[i].startDate, rJCDE[i].endDate, "full", rJCDE[i].allDay) + '</option>');
2090                        }
2091                    };
2092                } else {
2093                    $('#rDates').remove();
2094                    $('.save-row').remove();
2095                    $('.rDate').append("This event has ended. It ran from<br/>" + moment(thisCurrentEvent[0].startDate).format('MMM D, YYYY') + " to " + moment(thisCurrentEvent[0].recurringDetails.recurUntilDate).format('MMM D, YYYY') + ".");
2096                }
2097            });
2098        });
2099    });
2100}
2101
2102function checkHash() {
2103    if (window.location.hash) {
2104        loadView("side-featured-events", $featuredEventsContainer, sideFeaturedCount).then(function(results) {
2105            showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
2106            if (debugMode) {
2107                console.log("------------------------");
2108                console.log("pageLoadHash");
2109            }
2110            getHash(window.location.hash, "", function() {
2111                setViews = vHashes.join();
2112                setViewsLoad = setViews.replace("v=", "");
2113                if (setViewsLoad.length < 1) {
2114                    setViewsLoad = defaultView;
2115                };
2116                setFiltersMerged = "";
2117                setFilters = _.concat(f1Hashes, f2Hashes, f3Hashes, f4Hashes, f5Hashes, f6Hashes, f7Hashes, f8Hashes, f9Hashes, f10Hashes);
2118                setFiltersClean = _.compact(setFilters);
2119                setFiltersMerged = "&" + setFiltersClean.join("&");
2120                setFiltersLoad = setFiltersMerged;
2121                for (let i = 0; i < urlHashes.length; i++) {
2122                    setFiltersLoad = setFiltersLoad.replace(urlHashes[i], "");
2123                };
2124                setFiltersLoad = setFiltersLoad.replace(/&/g, ".").replace(/=/g, ".").replace(/,/g, filterLogic).replace(/\.\./g, ".");
2125                if (setFiltersLoad === ".") {
2126                    setFiltersLoad = "";
2127                }
2128                loadView(setViewsLoad, "", "all", "pageLoad").then(function(results) {
2129                    showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
2130                });
2131            });
2132        });
2133    } else {
2134        if (debugMode) {
2135            console.log("pageLoad: " + defaultView);
2136            console.log("------------------------");
2137        }
2138        loadView("side-featured-events", $featuredEventsContainer, sideFeaturedCount).then(function(results) {
2139            showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
2140            if (debugMode) {
2141                console.log("------------------------");
2142            }
2143            loadView(defaultView, "", "", "pageLoad").then(function(results) {
2144                showEvents(results.events, results.view, results.target, results.showLimit, results.origin);
2145            });
2146        });
2147    }
2148}
2149
2150function dateOutput(startDateIn, endDateIn, type, allDayIn) {
2151    if (allDayIn === "true") {
2152        var startDateM = moment.parseZone(startDateIn);
2153        var endDateM = moment.parseZone(endDateIn);
2154    } else {
2155        var startDateM = moment(startDateIn);
2156        var endDateM = moment(endDateIn);
2157    }
2158    if (startDateM.isSame(endDateM,'day')) {
2159        if (type == "full") {
2160            var dateOutput = startDateM.format('MMMM D, YYYY');
2161        } else {
2162            var dateOutput = startDateM.format('MMM D YYYY');
2163        }
2164    } else {
2165        if (startDateM.isSame(endDateM, 'year')) {
2166            if (startDateM.isSame(endDateM, 'month')) {
2167                var dateOutput = startDateM.format('MMM D') + ' - ' + endDateM.format('D YYYY');
2168            } else {
2169                var dateOutput = startDateM.format('MMM D') + ' - ' + endDateM.format('MMM D YYYY');
2170            }
2171        } else {
2172            var dateOutput = startDateM.format('MMM D YYYY') + ' - ' + endDateM.format('MMM D YYYY');
2173        }
2174    }
2175    return dateOutput;
2176}
2177
2178function imgWeekDay(day) {
2179    var daysOfWeek = ["Mon<span>day</span>", "Tue<span>sday</span>", "Wed<span>nesday</span>", "Thur<span>sday</span>", "Fri<span>day</span>", "Sat<span>urday</span>", "Sun<span>day</span>"];
2180    return daysOfWeek[day - 1];
2181}
2182
2183function imageOutput(image, startDateIn) {
2184    var startDateM = moment(startDateIn);
2185    if (image) {
2186        var imageOuput = '<div class="event-image" style="background-image:url(\'' + image.url + '\');"></div>';
2187    } else {
2188        var imageOuput = '<div class="event-image date-img"><div class="month">' + startDateM.format('MMM') + '</div><div class="day">' + startDateM.format('D') + '<div class="weekday">' + imgWeekDay(startDateM.isoWeekday()) + '</div></div></div>';
2189    }
2190    return imageOuput;
2191}
2192
2193function timeOutput(startDateIn, endDateIn, allDayIn, originalStart, originalEnd) {
2194    var timeOutput = "";
2195    if (allDayIn === "true") {
2196        timeOutput = 'All Day';
2197    } else {
2198        // var startDateInM = moment(startDateIn);
2199        // var originalStartM = moment(originalStart);
2200        // var endDateInM = moment(endDateIn);
2201        // var originalEndM = moment(originalEnd);
2202        var startDateInM = moment.parseZone(startDateIn);
2203        var originalStartM = moment.parseZone(originalStart || startDateIn);
2204        var endDateInM = moment.parseZone(endDateIn);
2205        var originalEndM = moment.parseZone(originalEnd || endDateIn);
2206        var startDateStdOffset; /*Fix to remove daylight savings time*/
2207        if (!moment().isDST()) {
2208            startDateStdOffset = originalStartM.utcOffset();
2209            var endDateStdOffset;
2210            endDateStdOffset = originalEndM.utcOffset();
2211            var startDateInOffsetM = startDateInM.utcOffset(startDateStdOffset);
2212            var endDateInOffsetM = endDateInM.utcOffset(endDateStdOffset);
2213        } else {
2214            var startDateInOffsetM = originalStartM;
2215            var endDateInOffsetM = originalEndM;
2216        }
2217        var startFormat = ["h"];
2218        var endFormat = [];
2219        if (startDateInOffsetM.minute() > 0) {
2220            startFormat.push(":mm");
2221        }
2222        if (startDateInOffsetM.isSame(endDateInOffsetM)) {
2223            startFormat.push(" A");
2224        } else {
2225            if (startDateInOffsetM.format('A') != endDateInOffsetM.format('A')) {
2226                startFormat.push(" A");
2227            }
2228            endFormat.push("h");
2229            if (endDateInOffsetM.minute() > 0) {
2230                endFormat.push(":mm");
2231            }
2232            endFormat.push(" A");
2233        }
2234        timeOutput = startDateInOffsetM.format(startFormat.join(""));
2235        if (endFormat.length) {
2236            timeOutput += " - " + endDateInOffsetM.format(endFormat.join(""));
2237        }
2238    }
2239    return timeOutput;
2240}
2241
2242function filterCheck(fcLogic, fcPush, fcEvent) {
2243    if (debugMode) {
2244        console.log("filterCheck");
2245    }
2246    var fMatch = 0;
2247    for (let i = 0; i < filterTexts.length; i++) {
2248        if (filterTexts[i]) {
2249            for (let iFT = 0; iFT < filterTexts[i].length; iFT++) {
2250                if (filterTexts[i][iFT]) {
2251                    var eventFilter = fcEvent['filter' + (i + 1)];
2252                    var eventFilterCheck = [];
2253                    if (Array.isArray(eventFilter)) {
2254
2255                        for (let iEF = 0; iEF < eventFilter.length; iEF++) {
2256                            eventFilterCheck.push(eventFilter[iEF].toLowerCase().replace(/[^A-Za-z0-9]/g, ""));
2257                        };
2258                        if ($.inArray(filterTexts[i][iFT], eventFilterCheck) != -1) {
2259                            fMatch++
2260                        }
2261                    }
2262                }
2263            };
2264        }
2265    };
2266    if (fcLogic === "Or") {
2267        if (fMatch > 0) {
2268            fcPush.push(fcEvent);
2269        }
2270    } else if (fcLogic === "And") {
2271        if (fMatch == filterTextsAll.length) {
2272            fcPush.push(fcEvent);
2273        }
2274    }
2275}
2276
2277function relatedEventsAjax() {
2278    $.ajax({
2279        url: currentDataURL.replace(/&amp;/g, '&'),
2280        success: function(URLData) {
2281            calculateRecurrences(URLData.events).then(function(resultsR) {
2282                eventDateChecker(URLData.events, resultsR, "related-events").then(function(results) {
2283                    jsonToCurrentData(results).then(function(results) {
2284                        var rJCDE = results.jsonToCurrentDataEvents;
2285                        rJCDE.sort(function(a, b) {
2286                            return +new Date(a.startDate) - +new Date(b.startDate);
2287                        });
2288                        for (let i = 0; i < rJCDE.length; i++) {
2289                            if (rJCDE[i].id != currentEventID) {
2290                                // if (moment(rJCDE[i].startDate).diff() > 0) {
2291                                    filterCheck(relatedEventsFilterLogic, relatedEvents, rJCDE[i]);
2292                                // }
2293                            }
2294                            if (relatedEvents.length >= 6) {
2295                                break;
2296                            }
2297                        };
2298                        if (relatedEvents.length > 0) {
2299                            getRelatedEvents(relatedEvents).then(function(results) {
2300                                $('.related-events .events').empty();
2301                                $('.related-events .events').append(results.events);
2302                                if (typeof afterHHRelatedEventsLoad == 'function') {
2303                                    setTimeout(function() {
2304                                        afterHHRelatedEventsLoad();
2305                                    }, 50);
2306                                }
2307                            });
2308                        } else {
2309                            $('.related-events .events').empty();
2310                            $('.related-events .events').append('<div><p style="text-align:center">No upcoming related events found.</p></div>');
2311                        }
2312                    });
2313                });
2314            });
2315        },
2316        error: function(data) {
2317            if (data.status == 200) {
2318                console.log("JSON Not Valid: " + currentDataURL);
2319            } else {
2320                console.log("Data URL Not Found: " + currentDataURL);
2321            }
2322        }
2323    });
2324}
2325
2326function afterHHRelatedEventsLoad(){
2327    $('.hh-events .related-events .event').matchHeight();
2328}
2329
2330function afterHHEventsLoad(){
2331    $('.hh-events.hh-events-block .event').matchHeight();
2332}
2333
2334function blockEvents() {
2335    $.ajax({
2336        url: currentDataURL.replace(/&amp;/g, '&'),
2337        success: function(URLData) {
2338            calculateRecurrences(URLData.events).then(function(resultsR) {
2339                eventDateChecker(URLData.events, resultsR, "hh-events-block").then(function(results) {
2340                    jsonToCurrentData(results).then(function(results) {
2341                        var rJCDE = results.jsonToCurrentDataEvents;
2342                        rJCDE.sort(function(a, b) {
2343                            return +new Date(a.startDate) - +new Date(b.startDate);
2344                        });
2345                        var blockEventsCount = 0;
2346                        if (hhEventsType == "current") {
2347                            for (let i = 0; i < rJCDE.length; i++) {
2348                                // if (moment(rJCDE[i].startDate).diff() > 0) {
2349                                    blockEventsCount++;
2350                                    hhEvents.push(rJCDE[i]);
2351                                    if (blockEventsCount == hhEventsLimit) {
2352                                        break;
2353                                    }
2354                                // }
2355                            };
2356                        } else {
2357                            for (let i = 0; i < rJCDE.length; i++) {
2358                                // if (moment(rJCDE[i].startDate).diff() > 0) {
2359                                    filterCheck(hhEventsFilterLogic, hhEvents, rJCDE[i]);
2360                                // }
2361                                if (hhEvents.length >= hhEventsLimit) {
2362                                    break;
2363                                }
2364                            };
2365                        }
2366                        if (hhEvents.length > 0) {
2367                            getBlockEvents(hhEvents).then(function(results) {
2368                                $('.hh-events-block .row.events').empty();
2369                                $('.hh-events-block .row.events').append(results.events);
2370                                if (typeof afterHHEventsBlockLoad == 'function') {
2371                                    setTimeout(function() {
2372                                        afterHHEventsBlockLoad();
2373                                    }, 50);
2374                                }
2375                            });
2376                        } else {
2377                            $('.hh-events-block .row.events').empty();
2378                            $('.hh-events-block .row.events').append('<div><p style="text-align:center">No upcoming events found.</p></div>');
2379                        }
2380                    });
2381                });
2382            });
2383        },
2384        error: function(data) {
2385            if (data.status == 200) {
2386                console.log("JSON Not Valid: " + currentDataURL);
2387            } else {
2388                console.log("Data URL Not Found: " + currentDataURL);
2389            }
2390        }
2391    });
2392}
2393

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.