PageSourceSearch

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

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

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.