PageSourceSearch

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

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

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.