PageSourceSearch

https://www.butte.edu/events/_files/js/hh-events.js

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

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.