PageSourceSearch

https://arenaskovde.se/Templates/Knowit/UX/Script/all.js

js arenaskovde.se collected 2026-09-26 16:24:10 UTC 75,545 bytes, 2,099 lines download raw bytes

1/* 
2    ==================================================
3    Mobile menu - NEW VERSION
4    ================================================== 
5*/
6
7$(function () {
8    $("nav.nav-mobile ul.menu-collapse").on(
9        "click",
10        "li.has-children .icon",
11        function () {
12            if ($(this).hasClass("auto-open")) {
13                $(this).next("ul").slideToggle(true);
14                $(this).closest("li").toggleClass("active");
15                return;
16            }
17
18            $(this).closest("li").toggleClass("active");
19
20            let apiUrl =
21                "/Templates/Knowit/Pages/MobileNavigation.aspx?pageId=" +
22                $(this).attr("data-id");
23
24            var myButton = $(this);
25            $.ajax({
26                dataType: "json",
27                url: apiUrl,
28                success: function (json) {
29                    var ul = myButton.next("ul");
30                    ul.html("");
31                    for (var i = 0; i < json.length; i++) {
32                        var obj = json[i];
33
34                        var li = null;
35
36                        if (obj.HasChildren) {
37                            li = $("<li class='has-children'></li>");
38                        } else {
39                            li = $("<li></li>");
40                        }
41
42                        var a = $("<a href='" + obj.Url + "'>" + obj.Name + "</a>");
43                        var btn = $(
44                            "<button type='button' data-id='" +
45                            obj.Id +
46                            "' class='icon'></button>"
47                        );
48                        var newUl = $('<ul class="subnav"></ul >');
49
50                        li.append(a);
51
52                        if (obj.HasChildren) {
53                            li.append(btn);
54                            li.append(newUl);
55                        }
56
57                        ul.append(li);
58                    }
59
60                    // Show the new menu list
61                    myButton.next("ul").slideToggle(true);
62                    myButton.toggleClass("expanded");
63                },
64            });
65        }
66    );
67});
68
69/* 
70    ==================================================
71    Mobile menu - OLD VERSION
72    ================================================== 
73*/
74
75$(function () {
76    $("nav.nav-mobile a.toggle-navigation-btn").on("click", (function (e) {
77        e.preventDefault();
78        $("nav.nav-mobile ul.menu-collapse").slideToggle("slow");
79        $("nav.nav-mobile a.toggle-navigation-btn").toggleClass("active");
80        $("body").toggleClass("nav-active");
81    }));
82
83    //toggle menu tabs
84    $(".menu-collapse li.menu-title").on("click", (function (e) {
85        if ($(this).hasClass("main-menu")) {
86            $(".menu-collapse li.menu-title").removeClass("active");
87            $(".menu-collapse li.menu").removeClass("active");
88            $(".menu-collapse").find(".main-menu").toggleClass("active", true);
89        } else if ($(this).hasClass("entry-links-menu")) {
90            $(".menu-collapse li.menu-title").removeClass("active");
91            $(".menu-collapse li.menu").removeClass("active");
92            $(".menu-collapse").find(".entry-links-menu").toggleClass("active", true);
93        }
94    }));
95
96    //expand sub-menu
97    $("nav.nav-mobile ul.menu-collapse li.active > .icon").each(function () {
98        $(this).next("ul").slideToggle(true);
99    });
100});
101
102/* 
103    ==================================================
104    Navigation - Megamenu
105    ================================================== 
106*/
107$(function () {
108    // Fixed navigation
109    $(window).on("scroll", (function () {
110        if ($(this).scrollTop() > 159)
111            $('nav[role="navigation"]').addClass("fixed");
112        else if ($('nav[role="navigation"]').hasClass("fixed"))
113            $('nav[role="navigation"]').removeClass("fixed");
114    }));
115
116    // Hover
117
118    var timeOut;
119    var timeOutMilliseconds = 500;
120    var navigation = $('nav[role="navigation"] ul.nav');
121    var megamenu = $('nav[role="navigation"] ul.nav .flyout');
122
123    function open() {
124        return $(navigation).hasClass("open");
125    }
126
127    function hasSubmenu(that) {
128        return $(that).children(".flyout").length != 0;
129    }
130
131    $('nav[role="navigation"] ul.nav > li').hover( 
132        function () {
133            var me = this;
134
135            if (!open())
136                timeOut = setTimeout(function () {
137                    showMegameny(me);
138                }, timeOutMilliseconds);
139            else showMegameny(me);
140        },
141        function () {
142            clearTimeout(timeOut);
143            $('nav[role="navigation"] ul.nav li').removeClass("focus");
144        }
145    );
146
147    function showMegameny(that) {
148        // Remove close class
149        if (!hasSubmenu(that) && open()) $(navigation).removeClass("open");
150
151        // Close
152        if (open()) $(megamenu).hide();
153        else $(megamenu).fadeOut();
154
155        // Open
156        if (hasSubmenu(that)) {
157            $(that).addClass("focus");
158
159            if (!open()) {
160                $(that).children(".flyout").stop(true, true).fadeIn();
161                $(navigation).addClass("open");
162            } else $(that).children(".flyout").show();
163        }
164    }
165
166    $('nav[role="navigation"] ul.nav').on("mouseleave", function () {
167        // Closes megamenu when user moves cursor i the header
168        if (open()) {
169            $(megamenu).fadeOut();
170            $(navigation).removeClass("open");
171
172            $('nav[role="navigation"] ul.nav li').removeClass("focus");
173        }
174    });
175
176    $(megamenu).on("mouseover", function (e) {
177        // Check if its not a derived container that is clicked
178        if ($(this).is(e.target) && $(this).has(e.target).length === 0) {
179            // Inactivate events once
180            $('nav[role="navigation"]').off("mouseleave");
181
182            $(navigation).removeClass("open");
183            $('nav[role="navigation"] ul.nav li').removeClass("focus");
184            $(megamenu).fadeOut();
185        }
186    });
187});
188
189/* 
190    ==================================================
191    Toggle
192    ================================================== 
193*/
194
195$(function () {
196    //vars
197    var currentBlock = false;
198    var selectedBlock = false;
199    var allTabBlocks = $(".tabblock");
200
201    //init
202    $(".toggle-content.block-1").addClass("show");
203
204    //find all tabblocks and give them unique id's to prevent conflicts
205    $.each(allTabBlocks, function (i, block) {
206        $(block).addClass("toggle-" + i);
207    });
208
209    //toggle on click
210    $(".tabblock nav a").on("click", (function (e) {
211        e.preventDefault();
212
213        //Check if already selected
214        if (!$(this).parent().hasClass("focus")) {
215            //find parent to select the right box
216            currentBlock =
217                "." + $(this).closest(".tabblock").attr("class").replace(/ /g, ".");
218
219            //remove the currently visible content
220            $(currentBlock + " .toggle-content.show").removeClass("show");
221
222            //find and show the newly selected content
223            selectedBlock = currentBlock + " .toggle-content." + this.className;
224            $(selectedBlock).addClass("show");
225
226            //remove and assign nav indicator
227            $(currentBlock + " li.focus a")
228                .parent()
229                .removeClass("focus");
230            $(this).parent().addClass("focus");
231        }
232    }));
233});
234
235
236/* 
237    ==================================================
238    Slideshow
239    ================================================== 
240    Requires cycle plugin and jquery
241*/
242
243$(function () {
244
245    // Slideshow
246    $(".slideshow").each(function () {
247        // Init
248        var container = this;
249        var firstRun = true;
250
251        // Defaults for cycle plugin
252        var slideshowFx = "fade";
253        var slideshowDelay = 0;
254        var slideshowTimeOut = 3000;
255        if (typeof globalSlideshowTimeOut != "undefined") {
256            slideshowTimeOut = globalSlideshowTimeOut;
257        }
258
259        var pauseByDefault = false;
260
261
262        // Controls
263        var slides = $(container).find(".slides"); // Div containing all slides
264        var next = $(container).find(".next"); // Next slide
265        var prev = $(container).find(".prev"); // Prev slide
266        var start = $(container).find(".start"); // Start slideshow
267        var stop = $(container).find(".stop"); // Stop slideshow
268
269        // Pager
270        var pager = $(container).find(".pager"); // Set to null if no pager
271
272        // Liveregion, used by screenreaders
273        var liveRegion = $(container).find(".liveregion");
274
275        // Caption
276        var caption = ".caption"; // Classname of item containing the captiontext
277        var captionContainer = $(container).find(".caption-container"); // Caption display container
278
279
280        var totalSlides = $(slides).children("li").length;
281
282        // Check if there is more then one image
283        if ($(slides).children().length <= 1) {
284            // Hide all controls
285            $(start).hide();
286            $(stop).hide();
287            $(next).hide();
288            $(prev).hide();
289            $(pager).hide();
290
291            // Show caption
292            var dataCaption = $(slides).children().children(caption).html();
293            if (dataCaption != undefined) {
294                // Fade in caption if set
295                if (captionContainer.css("display") == "none") captionContainer.hide();
296
297                $(captionContainer).html(dataCaption);
298            } else {
299                // Fade out caption if not set
300                captionContainer.hide();
301            }
302
303            return 0;
304        }
305
306        // Cycle
307        $(slides).cycle({
308            fx: slideshowFx,
309            delay: slideshowDelay,
310            timeout: slideshowTimeOut,
311            containerResize: true,
312            slideResize: true,
313            width: "100%",
314            fit: 1,
315            next: next,
316            prev: prev,
317            pager: pager,
318            before: function (curr, next, opts) {
319                // Liveregion
320                if (liveRegion !== undefined) {
321                    var activeSlide = opts.nextSlide + 1;
322                    if (firstRun) {
323                        activeSlide = 1;
324                        firstRun = false;
325                    }
326
327                    var liveRegionTextTemplate = window.slideshowStrings.liveRegionText;
328
329                    liveRegionTextTemplate = liveRegionTextTemplate.replace(
330                        "{0}",
331                        activeSlide
332                    );
333                    liveRegionTextTemplate = liveRegionTextTemplate.replace(
334                        "{1}",
335                        totalSlides
336                    );
337
338                    $(liveRegion).text(liveRegionTextTemplate);
339                }
340
341                // Caption
342                var dataCaption = $(next).children(caption).html();
343                if (dataCaption != undefined) {
344                    // Fade in caption if set
345                    if (captionContainer.css("display") == "none")
346                        captionContainer.fadeIn();
347
348                    $(captionContainer).html(dataCaption);
349                } else {
350                    // Fade out caption if not set
351                    captionContainer.fadeOut();
352                }
353            },
354            pagerAnchorBuilder: function (idx, slide) {
355                var listItem = document.createElement("li");
356                var button = document.createElement("button");
357                var pagerScreenReaderDesc = document.createElement("span");
358
359                button.setAttribute("data-slide", idx);
360                button.setAttribute("aria-disabled", true);
361                button.setAttribute("tabindex", -1);
362                button.innerText = idx;
363
364                pagerScreenReaderDesc.classList.add("visuallyhidden");
365                pagerScreenReaderDesc.innerText = window.slideshowStrings.pagerText;
366
367                button.appendChild(pagerScreenReaderDesc);
368                listItem.appendChild(button);
369
370                return listItem.outerHTML;
371
372            },
373        });
374
375        // Pause
376        if (pauseByDefault) {
377            $(slides).cycle("pause");
378            HideControlElement(stop);
379        } else {
380            HideControlElement(start);
381        }
382
383        // Controls
384        $(start).on("click", (function (e) {
385            e.preventDefault();
386            $(slides).cycle("resume");
387            HideControlElement(start);
388            ShowControlElement(stop);
389        }));
390
391        $(stop).on("click", (function (e) {
392            e.preventDefault();
393            $(slides).cycle("pause");
394            HideControlElement(stop);
395            ShowControlElement(start);
396        }));
397        function HideControlElement(element) {
398            element.hide().attr("aria-hidden", "true");
399        }
400        function ShowControlElement(element) {
401            element.show().attr("aria-hidden", "false");
402        }
403    });
404});
405
406
407/*
408    ==================================================
409    Timeline
410    ==================================================
411*/
412$(function () {
413    Array.prototype.slice.call(document.querySelectorAll('.TimelineBlock.AccordionContent .Accordion')).forEach(function (accordion) {
414
415        var allowMultiple = accordion.hasAttribute('data-allow-multiple');
416        var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle');
417
418        accordion.addEventListener('click', function (event) {
419            var target = event.target;
420
421            if (target.classList.contains('Accordion-trigger')) {
422                // Check if the current toggle is expanded.
423                var isExpanded = target.getAttribute('aria-expanded') == 'true';
424                var panel = document.getElementById(target.getAttribute('aria-controls'));
425                target.classList.toggle('fa-plus');
426                target.classList.toggle('fa-minus');
427
428                $(panel).slideToggle('slow');
429
430                if (!isExpanded) {
431                    // Set the expanded state on the triggering element
432                    target.setAttribute('aria-expanded', 'true');
433                    // Hide the accordion sections, using aria-controls to specify the desired section
434                    document.getElementById(target.getAttribute('aria-controls')).removeAttribute('hidden');
435
436
437                    // If toggling is not allowed, set disabled state on trigger
438                    if (!allowToggle) {
439                        target.setAttribute('aria-disabled', 'true');
440                    }
441                }
442                else if (allowToggle && isExpanded) {
443                    // Set the expanded state on the triggering element
444                    target
445                    target.setAttribute('aria-expanded', 'false');
446                    // Hide the accordion sections, using aria-controls to specify the desired section
447                    document.getElementById(target.getAttribute('aria-controls')).setAttribute('hidden', '');
448                }
449
450            }
451        });
452    });
453});
454
455/* 
456    ==================================================
457    Project Filter - Tabs + Accordion
458    ================================================== 
459*/
460$(function () {
461    if ($(".project-filter").length) {
462        if ($(".project-filter").hasClass("project-google-map")) {
463            $(this).find(".filter-menu").accordion();
464
465            $(window).on("load resize", function () {
466                if (window.innerWidth > 992) {
467                    $(".project-google-map").find(".filter-menu").accordion("destroy");
468                } else {
469                    $(".project-google-map").find(".filter-menu").accordion({
470                        heightStyle: "content",
471                        collapsible: true,
472                        clearStyle: true,
473                        active: 0,
474                    });
475                }
476            });
477        } else {
478            $(this).find(".filter-menu").tabs();
479        }
480    }
481});
482
483/* 
484    ==================================================
485    Files list - Area
486    ================================================== 
487*/
488$(function () {
489    if ($("#accordion").length) {
490        $("#accordion").accordion({
491            heightStyle: "content",
492            collapsible: true,
493            clearStyle: true,
494            active: currentActive,
495        });
496    }
497});
498
499$(function () {
500    if ($("#accordion-billboard").length) {
501        $("#accordion-billboard").accordion({
502            heightStyle: "content",
503            collapsible: true,
504            clearStyle: true,
505            active: false,
506        });
507    }
508});
509
510/* 
511    ==================================================
512    Contact - Area
513    ================================================== 
514*/
515$(document).ready(function () {
516    $(".btn-contact").on("click", (function (e) {
517        e.preventDefault();
518        $(".ContactArea").slideToggle();
519        $(".btn-contact").toggleClass("close");
520    }));
521
522    $(".contactcard-area").each(function (index) {
523        $(this).children().first().wrapInner("<strong></strong>");
524    });
525});
526
527/* 
528    ==================================================
529    Contact form
530    ================================================== 
531*/
532
533$(document).ready(function () {
534    $(".ContactFormDDL").on("change", function (e) {
535        var i = $("option:selected", this).index();
536        $(this).parent().find(".how-to-contact").hide().eq(i).show();
537        e.preventDefault();
538    });
539
540    function checkToggle(id) {
541        if (id == "fileToggleBtn") {
542            var toggleVal = $(".txtToggleUpload").val();
543
544            if ($(".txtToggleUpload").val() == "show") {
545                $(".txtToggleUpload").val("hide");
546            } else {
547                $(".txtToggleUpload").val("show");
548            }
549        } else if (id == "mapToggleBtn") {
550            var toggleMapVal = $(".txtToggleMap").val();
551
552            if ($(".txtToggleMap").val() == "show") {
553                $(".txtToggleMap").val("hide");
554            } else {
555                $(".txtToggleMap").val("show");
556            }
557        }
558    }
559
560    $(".pull-down-button").on("click", (function (e) {
561        $(this).toggleClass("expanded");
562
563        var callbackMethod = $(this).hasClass("expanded") ? "on-open" : "on-close";
564
565        var callback = eval(jQuery(e.currentTarget).data(callbackMethod));
566
567        $(this)
568            .siblings(".pull-down-container")
569            .first()
570            .slideToggle({
571                duration: 500,
572                done: function () {
573                    if (typeof callback == "function") {
574                        callback();
575                    }
576                },
577            });
578
579        checkToggle(this.id);
580
581        e.preventDefault();
582    }));
583
584    if (
585        $(".txtToggleUpload").val() == "show" ||
586        $(".txtToggleUpload").val() == "formerror"
587    ) {
588        $("#fileToggleBtn").toggleClass("expanded");
589
590        $("#fileToggleBtn").siblings(".pull-down-container").first().slideToggle({
591            duration: 500,
592        });
593    }
594    if (
595        $(".txtToggleMap").val() == "show" ||
596        $(".txtToggleMap").val() == "formerror"
597    ) {
598        $("#mapToggleBtn").toggleClass("expanded");
599
600        $("#mapToggleBtn")
601            .siblings(".pull-down-container")
602            .first()
603            .slideToggle({
604                duration: 500,
605                complete: function () {
606                    InitializeGoogleMaps();
607                },
608            });
609    }
610});
611
612/* 
613    ==================================================
614    Project map filtering
615    ================================================== 
616*/
617
618var map; // Contains the google map object
619var coordinates = []; // Result from JSON request
620var markers = []; //  Google map markers wrapped in a custom object
621var zoomLevel = 1;
622
623function createMapIcon(color, size) {
624    return {
625        //path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
626        path: google.maps.SymbolPath.CIRCLE,
627        fillColor: color,
628        fillOpacity: 1,
629        anchor: new google.maps.Point(0, 0),
630        strokeWeight: 4,
631        strokeColor: "#ffffff",
632        strokeOpacity: 1,
633        scale: size,
634    };
635}
636
637function createCategoryList(jsonObj) {
638    var result = "";
639
640    for (var i = 0; i < jsonObj.length; i++) {
641        result +=
642            "<li>" +
643            '<span class="color-category" style="background:' +
644            jsonObj[i]["Color"] +
645            '"></span>' +
646            "</li>";
647    }
648
649    return result;
650}
651
652function initMap() {
653    map = new google.maps.Map(document.getElementById("project-google-map"), {
654        center: { lat: 58.3917535, lng: 13.8437657 },
655        zoom: 10,
656        disableDefaultUI: true,
657    });
658
659    google.maps.event.addListener(map, "zoom_changed", function () {
660        var i, prevZoomLevel;
661
662        prevZoomLevel = zoomLevel;
663
664        map.getZoom() < 16 ? (zoomLevel = 1) : (zoomLevel = 2);
665
666        if (prevZoomLevel !== zoomLevel) {
667            for (i = 0; i < markers.length; i++) {
668                if (zoomLevel === 2) {
669                    markers[i].marker.setIcon(markers[i].bigIcon);
670                } else {
671                    markers[i].marker.setIcon(markers[i].defaultIcon);
672                }
673            }
674        }
675    });
676
677    var xhr = new XMLHttpRequest();
678    xhr.open("GET", projectMapSettings.coordinatesServiceUrl);
679    xhr.onload = function () {
680        if (xhr.status === 200) {
681            var jsonResult = JSON.parse(xhr.responseText);
682            coordinates = jsonResult; // Save for filtering
683
684            var infowindow = new google.maps.InfoWindow(); /* SINGLE */
685            for (var i = 0; i < jsonResult.length; i++) {
686                var color = jsonResult[i]["ColorizedCategories"][0]["Color"];
687
688                var contentString =
689                    '<div id="content">' +
690                    '<div id="siteNotice">' +
691                    "</div>" +
692                    '<h1 id="firstHeading" class="firstHeading"><a href="' +
693                    jsonResult[i]["Link"] +
694                    '">' +
695                    jsonResult[i]["Heading"] +
696                    "</a></h1>" +
697                    '<div class="project-categories"><span class="subheading">Kategorier</span><ul>' +
698                    createCategoryList(jsonResult[i]["ColorizedCategories"]) +
699                    "</ul></div>" +
700                    '<div id="bodyContent" class="project-map-status"><p>' +
701                    jsonResult[i]["Status"] +
702                    "</p>" +
703                    "</div>" +
704                    "</div>";
705
706                var icon = createMapIcon(color, 9);
707                var bigIcon = createMapIcon(color, 13);
708
709                var marker = new google.maps.Marker({
710                    position: new google.maps.LatLng(
711                        jsonResult[i]["Latitude"],
712                        jsonResult[i]["Longitude"]
713                    ),
714                    icon: icon,
715                    map: map,
716                    info: contentString,
717                });
718
719                google.maps.event.addListener(marker, "click", function () {
720                    infowindow.setContent(this.info);
721                    infowindow.open(map, this);
722                });
723
724                var wrapper = {
725                    marker: marker,
726                    categories: jsonResult[i]["ProjectCategories"],
727                    defaultIcon: icon,
728                    bigIcon: bigIcon,
729                };
730
731                markers.push(wrapper);
732            }
733        } else {
734            console.log("Request failed.  Returned status of " + xhr.status);
735        }
736    };
737    xhr.send();
738}
739
740
741let polygonData = [];
742let GlobalOngoingMap;
743function initProjectMap(zoomLevelValue, startCoordinates, catId = null) {
744    GlobalOngoingMap = new google.maps.Map(document.getElementById('project-locations-google-map'), {
745        center: { lat: Number(startCoordinates[0]), lng: Number(startCoordinates[1]) },
746        zoom: zoomLevelValue,
747        disableDefaultUI: true,
748    });
749
750    //Fixes a array with coordinates from string
751    let htmlCollection = document.getElementsByClassName("maps-data");
752    let allMapData = Array.prototype.slice.call(htmlCollection);
753
754
755    allMapData.forEach(data => {
756        let coordinates = [];
757        let tempCoordinates = data.dataset.coordinates.replaceAll(/\s/g, '').split(";");
758        tempCoordinates.forEach(locatinoCoord => {
759            let location = locatinoCoord.split(",");
760            if (Number(location[0]) > 0 && Number(location[1]) > 0) {
761                let coordinateObj = { lat: Number(location[0]), lng: Number(location[1]) }
762                coordinates.push(coordinateObj);
763            }
764        });
765
766        //changes opacity if there is a selected filter
767        let opacity = 0.35;
768        if (data.dataset.category == catId && catId != null) {
769            opacity = 0.8
770        }
771
772        //pushes data to polygonData array to keep when recreating polygons
773        polygonData.push({
774            cords: coordinates,
775            color: data.dataset.color,
776            opacity: opacity,
777            width: 2,
778            indexId: data.dataset.category
779        })
780    });
781    createMapPolygons(polygonData, GlobalOngoingMap);
782}
783
784let lastShownId = "";
785//Holds map polygons so they can be removed
786let mapPolygons = [];
787function createMapPolygons(polygonObjecArray, map) {
788    //Adds the polygons to the map
789    polygonObjecArray.forEach(item => {
790        let x = new google.maps.Polygon({
791            paths: item.cords,
792            strokeColor: item.color,
793            strokeOpacity: item.opacity,
794            strokeWeight: item.width,
795            fillColor: item.color,
796            fillOpacity: item.opacity,
797            indexID: item.indexId
798        });
799        mapPolygons.push(x);
800        x.setMap(map);
801
802        //Adds event listener to recreate polygons with the right opacity and display the right content
803        google.maps.event.addListener(x, 'click', function (event) {
804            const statusBar = document.getElementById(x.indexID + "-statusbar");
805            const lastStatusBar = document.getElementById(lastShownId + "-statusbar");
806            const elem = document.getElementById(x.indexID);
807            const selectedFilterButtons = document.querySelectorAll('a[data-id="' + x.indexID + '"]');
808            const lastSelectedFilterButtons = document.querySelectorAll('a[data-id="' + x.indexID + '"]');
809            const url = new URL(window.location);
810
811
812            //displays the right content based on id
813            if (lastShownId == "") {
814                document.getElementById("start-article").classList.add("hidden");
815                document.getElementById("start-wideBlock").classList.add("hidden");
816                if (document.getElementById("startpage-statusbar") != null) {
817                    document.getElementById("startpage-statusbar").classList.add("hidden");
818                }
819                window.history.pushState({}, '', window.location.origin + window.location.pathname);
820            }
821            if (elem != undefined) {
822                elem.classList.remove("hidden");
823                selectedFilterButtons.forEach(selectedButton => {
824                    selectedButton.classList.add("active");
825                })
826                if (statusBar != null) {
827                    statusBar.classList.remove("hidden");
828                }
829                url.searchParams.set('category', x.indexID);
830                window.history.pushState({}, '', url);
831
832                if (lastShownId != "" && x.indexID != lastShownId) {
833                    document.getElementById(lastShownId).classList.add("hidden");
834                    lastSelectedFilterButtons.forEach(lastSelectedButton => {
835                        lastSelectedButton.classList.add("active");
836                    })
837                    if (lastStatusBar != null) {
838                        lastStatusBar.classList.add("hidden");
839                    }
840                }
841                if (x.indexID == lastShownId) {
842                    elem.classList.add("hidden");
843                    lastSelectedFilterButtons.forEach(lastSelectedButton => {
844                        lastSelectedButton.classList.add("active");
845                    })
846                    if (lastStatusBar != null) {
847                        lastStatusBar.classList.add("hidden");
848                    }
849                    document.getElementById("start-article").classList.remove("hidden");
850                    document.getElementById("start-wideBlock").classList.remove("hidden");
851                    if (document.getElementById("startpage-statusbar") != null) {
852                        document.getElementById("startpage-statusbar").classList.remove("hidden");
853                    }
854                    window.history.pushState({}, '', window.location.origin + window.location.pathname);
855                }
856                removeLastActiveFilterStyle();
857            }
858
859            //removes active polygons and add less opacity to selected polygon then create new polygons
860            let newPolygons = [];
861            for (i in mapPolygons) {
862                let temp = [];
863                if (polygonData[i].indexId == x.indexID && lastShownId != x.indexID) {
864                    temp = polygonData[i];
865                    temp.opacity = 0.8;
866                    newPolygons.push(temp);
867                } else {
868                    temp = polygonData[i];
869                    temp.opacity = 0.35;
870                    newPolygons.push(temp);
871                }
872                mapPolygons[i].setMap(null);
873            }
874            mapPolygons = [];
875            if (lastShownId == x.indexID) {
876                lastShownId = "";
877            } else {
878                lastShownId = x.indexID;
879            }
880            createMapPolygons(newPolygons, map)
881        });
882    });
883}
884
885$(document).ready(function () {
886    let projectLocationMap = document.getElementById("project-locations-google-map");
887    if (projectLocationMap != undefined) {
888        let zoomLevelValue = document.getElementById("map-props").dataset.zoomlevel;
889        let startCoordinates = document.getElementById("map-props").dataset.startcoord;
890        startCoordinates = startCoordinates.replaceAll(/\s/g, '');
891        startCoordinates = startCoordinates.split(',');
892
893        //Get filter category id
894        let params = (new URL(document.location)).searchParams;
895        let catId = params.get('category');
896        let statusBar = document.getElementById(catId + "-statusbar");
897
898        initProjectMap(Number(zoomLevelValue), startCoordinates, catId);
899
900        if (catId != null || catId != undefined) {
901            lastShownId = catId
902            document.getElementById("start-article").classList.add("hidden");
903            document.getElementById("start-wideBlock").classList.add("hidden");
904            if (document.getElementById("startpage-statusbar") != null) {
905                document.getElementById("startpage-statusbar").classList.add("hidden");
906            }
907            document.getElementById(catId).classList.remove("hidden");
908            document.querySelector('a[data-id="' + lastShownId + '"]').classList.add("active");
909            if (statusBar != null) {
910                statusBar.classList.remove("hidden");
911            }
912        }
913
914        const resetFilters = document.querySelectorAll(".reset-ongoing-filter");
915        resetFilters.forEach(resetFilter => {
916            resetFilter.addEventListener("click", function (e) {
917                e.preventDefault();
918                statusBar = document.getElementById(lastShownId + "-statusbar");
919                //Push url to history
920                const url = new URL(window.location.origin + window.location.pathname);
921                window.history.pushState({}, '', url);
922
923                let descriptions = Array.prototype.slice.call(document.getElementsByClassName("project-description"));
924                descriptions.forEach(descriptionElement => {
925                    if (!descriptionElement.classList.contains("hidden")) {
926                        descriptionElement.classList.add("hidden");
927                        if (statusBar != null) {
928                            statusBar.classList.add("hidden");
929                        }
930                    }
931                })
932                document.getElementById("start-article").classList.remove("hidden");
933                document.getElementById("start-wideBlock").classList.remove("hidden");
934                if (document.getElementById("startpage-statusbar") != null) {
935                    document.getElementById("startpage-statusbar").classList.remove("hidden");
936                }
937
938                removeLastActiveFilterStyle();
939
940                for (i in mapPolygons) {
941                    polygonData[i].opacity = 0.35;
942                    mapPolygons[i].setMap(null);
943                }
944                mapPolygons = [];
945                lastShownId = "";
946                createMapPolygons(polygonData, GlobalOngoingMap)
947            })
948        })
949
950        document.querySelector(".projects-map-filter.project-filter #ui-id-1").addEventListener("click", function (e) {
951            if (window.outerWidth < 992) {
952                toggleFilterMenuOnGoingProjects(e.target);
953            }
954        })
955    }
956})
957
958function toggleFilterMenuOnGoingProjects(target) {
959    if (!target.classList.contains("open")) {
960        target.classList.add("open");
961        document.querySelector(".projects-map-filter.project-filter .filter-menu-links").classList.add("open");
962        document.querySelector(".projects-map-filter.project-filter .ui-tabs-panel.ui-corner-bottom.ui-widget-content").ariaHidden = true;
963    } else {
964        target.classList.remove("open");
965        document.querySelector(".projects-map-filter.project-filter .filter-menu-links").classList.remove("open");
966        document.querySelector(".projects-map-filter.project-filter .ui-tabs-panel.ui-corner-bottom.ui-widget-content").ariaHidden = false;
967    }
968}
969
970// let lastActiveFilterId = null;
971function activateFilter(e) {
972    e.preventDefault();
973    let categoryId = e.target.dataset.id;
974
975    if (lastShownId == categoryId) {
976        return;
977    }
978
979    //show/hide content areas and text
980    if (categoryId != null) {
981        const url = new URL(window.location);
982        const statusBar = document.getElementById(categoryId + "-statusbar");
983        const lastStautsBar = document.getElementById(lastShownId + "-statusbar");
984        url.searchParams.set('category', categoryId);
985        window.history.pushState({}, '', url);
986
987        let descriptions = Array.prototype.slice.call(document.getElementsByClassName("project-description"));
988        descriptions.forEach(descriptionElement => {
989            if (descriptionElement.id == categoryId) {
990                if (descriptionElement.classList.contains("hidden")) {
991                    document.getElementById("start-article").classList.add("hidden");
992                    document.getElementById("start-wideBlock").classList.add("hidden");
993                    if (document.getElementById("startpage-statusbar") != null) {
994                        document.getElementById("startpage-statusbar").classList.add("hidden");
995                    }
996                    descriptionElement.classList.remove("hidden");
997                    if (lastStautsBar != null) {
998                        lastStautsBar.classList.add("hidden");
999                    }
1000                    var filterButtons = document.querySelectorAll('a[data-id="' + e.target.dataset.id + '"]');
1001                    filterButtons.forEach((button) => {
1002                        if (!button.classList.contains("active")) {
1003                            button.classList.add("active");
1004                        }
1005                    })
1006
1007                    removeLastActiveFilterStyle();
1008
1009                    lastShownId = descriptionElement.id
1010                }
1011            } else {
1012                descriptionElement.classList.add("hidden");
1013                if (statusBar != null) {
1014                    statusBar.classList.remove("hidden");
1015                }
1016            }
1017        })
1018        //removes active polygons and add less opacity to selected polygon then create new polygons
1019        let newPolygons = [];
1020        for (i in mapPolygons) {
1021            let temp = [];
1022            if (polygonData[i].indexId == categoryId) {
1023                temp = polygonData[i];
1024                temp.opacity = 0.8;
1025                newPolygons.push(temp);
1026            } else {
1027                temp = polygonData[i];
1028                temp.opacity = 0.35;
1029                newPolygons.push(temp);
1030            }
1031            mapPolygons[i].setMap(null);
1032        }
1033        mapPolygons = [];
1034        createMapPolygons(newPolygons, GlobalOngoingMap)
1035    } else {
1036        document.getElementById("start-article").classList.remove("hidden");
1037        document.getElementById("start-wideBlock").classList.remove("hidden");
1038        if (document.getElementById("startpage-statusbar") != null) {
1039            document.getElementById("startpage-statusbar").classList.remove("hidden");
1040        }
1041    }
1042}
1043
1044function removeLastActiveFilterStyle() {
1045    if (lastShownId != "") {
1046        let prevElem = document.querySelectorAll('a[data-id="' + lastShownId + '"]');
1047        prevElem.forEach((element) => {
1048            if (element.classList.contains("active")) {
1049                element.classList.remove("active");
1050            }
1051        })
1052    }
1053}
1054
1055$(function () {
1056    if (googleMapsIsEnabled()) {
1057        initMap();
1058    }
1059});
1060
1061var defaultColor = "#CCCCCC";
1062var hoverColor = "rgba(205, 230, 141,1)";
1063var selectedColor = "#B9E600";
1064
1065// string.format (override)
1066if (!String.prototype.format) {
1067    String.prototype.format = function () {
1068        var args = arguments;
1069        return this.replace(/{(\d+)}/g, function (match, number) {
1070            return typeof args[number] != "undefined" ? args[number] : match;
1071        });
1072    };
1073}
1074
1075function googleMapsIsEnabled() {
1076    return (
1077        typeof projectMapSettings !== "undefined" &&
1078        projectMapSettings.showGoogleMap &&
1079        projectMapSettings.coordinatesServiceUrl !== ""
1080    );
1081}
1082
1083function filterListBySelector(selector) {
1084    $(".list-projects-block .list-item")
1085        .addClass("hidden-project")
1086        .filter(selector)
1087        .removeClass("hidden-project");
1088}
1089
1090function setListingHeader(text) {
1091    $("#project-listing-header").html(
1092        text +
1093        " <span class='list-projects-count'>" +
1094        $(".list-projects-block .list-item:not(.hidden-project)").length +
1095        "</span>"
1096    );
1097}
1098
1099function clearMapStyle() {
1100    // Clear color style
1101    var mapItems = document.getElementsByClassName("map-item");
1102    for (var i = 0; i < mapItems.length; i++) {
1103        removeClass(mapItems[i], "map-item-selected");
1104        mapItems[i].setAttribute("style", "fill:'" + defaultColor + "' ");
1105    }
1106
1107    // Clear labels
1108    $(".projects-map-graphic .text:visible").hide();
1109}
1110
1111function colorMapElements(id, color) {
1112    $(".projects-map-graphic .filter-cat-" + id)
1113        .get()
1114        .forEach(function (element) {
1115            if (!hasClass(element, "map-item-selected")) {
1116                $(element).css({ fill: color });
1117                $(element).next(".text").toggle();
1118            }
1119        });
1120}
1121
1122function colorMapElement(mapElement, color) {
1123    if (!hasClass(mapElement, "map-item-selected")) {
1124        mapElement.css({ fill: color });
1125    }
1126}
1127
1128function colorMapSubElements(subElementsArr, color) {
1129    subElementsArr.forEach(function (element) {
1130        if (!!hasClass(element, "map-item-selected")) {
1131            $(element).css({ fill: color });
1132        }
1133    });
1134}
1135
1136function munListHover(hoverElement, color, cursor) {
1137    var mapElement = $(
1138        ".projects-map-graphic #" + hoverElement.parent().attr("data-name")
1139    );
1140
1141    // Mariestad consists of several paths
1142    if (mapElement.attr("id") == "Mariestad") {
1143        colorMapSubElements(mapElement.find(".map-item").get(), color);
1144        mapElement.find(".map-item").css("cursor", cursor);
1145        if (!hasClass(mapElement.find(".map-item").first(), "map-item-selected")) {
1146            mapElement.find(".text").toggle();
1147        }
1148    } else {
1149        if (!hasClass(mapElement, "map-item-selected")) {
1150            mapElement.next(".text").toggle();
1151        }
1152        colorMapElement(mapElement, color);
1153        mapElement.css("cursor", cursor);
1154    }
1155}
1156
1157function mapHover(hoverElement, color, cursor, show) {
1158    if ($(hoverElement).attr("id").indexOf("Mariestad") > -1) {
1159        var subElements = $(hoverElement).siblings("path");
1160        if (!hasClass(hoverElement, "map-item-selected")) {
1161            $(hoverElement).css({ fill: color });
1162            subElements.css({ fill: color });
1163            $(hoverElement).parent(".map-group").find(".text").toggle();
1164        }
1165        subElements.css("cursor", cursor);
1166    } else if (!hasClass(hoverElement, "map-item-selected")) {
1167        $(hoverElement).css({ fill: color });
1168        $(hoverElement).next(".text").toggle();
1169    }
1170    $(hoverElement).css("cursor", cursor);
1171}
1172
1173function clearFilter() {
1174    $(".filter-menu-links a").removeClass("filter-menu-selected");
1175}
1176
1177/* IE 11 hack functions */
1178
1179function addClass(element, cssClass) {
1180    if (element.length)
1181        element.attr("class", element.attr("class") + " " + cssClass);
1182    else $(element).attr("class", $(element).attr("class") + " " + cssClass);
1183}
1184
1185function hasClass(element, cssClass) {
1186    if (element.length) return element.attr("class").indexOf(cssClass) >= 0;
1187    else return $(element).attr("class").indexOf(cssClass) >= 0;
1188}
1189
1190function removeClass(element, cssClass) {
1191    if (element.length)
1192        return element.attr("class", element.attr("class").replace(cssClass, ""));
1193    else
1194        return $(element).attr(
1195            "class",
1196            $(element).attr("class").replace(cssClass, "")
1197        );
1198}
1199
1200function getParameterByName(name, url) {
1201    if (!url) {
1202        url = window.location.href;
1203    }
1204
1205    name = name.replace(/[\[\]]/g, "\\$&");
1206    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
1207        results = regex.exec(url);
1208    if (!results) return null;
1209    if (!results[2]) return "";
1210    return decodeURIComponent(results[2].replace(/\+/g, " "));
1211}
1212
1213function setParameter(name, value) {
1214    var re = new RegExp("([?&])" + name + "=.*?(&|$)", "i");
1215    var search = window.location.search;
1216    var hash = window.location.hash;
1217    var separator = search.indexOf("?") !== -1 ? "&" : "?";
1218
1219    if (search.match(re)) {
1220        search = search.replace(
1221            re,
1222            "$1" + name + "=" + encodeURIComponent(value) + "$2"
1223        );
1224    } else {
1225        search = search + separator + name + "=" + encodeURIComponent(value);
1226    }
1227
1228    history.replaceState(null, null, search + hash);
1229}
1230
1231$(function () {
1232    function setSelected(elem) {
1233        setParameter("cat", elem.data("id"));
1234        let selectedTab = elem.closest("div").attr("id");
1235
1236        if (selectedTab.length) {
1237            setParameter("t", selectedTab);
1238        } else {
1239            setParameter("t", "");
1240        }
1241    }
1242
1243    // MUNICIPALITIES LIST - CLICK
1244    $(".municipalities-filter a").on("click", function (e) {
1245        e.preventDefault();
1246
1247        var li = $(this).parent();
1248        var id = li.attr("data-id");
1249        var name = li.attr("data-name");
1250
1251        setSelected(li);
1252
1253        $(".filter-menu-links a").removeClass("filter-menu-selected");
1254        $(this).addClass("filter-menu-selected");
1255
1256        filterListBySelector(".filter-mun-" + id);
1257
1258        setListingHeader(listingHeadingFormat.format("i " + name));
1259
1260        clearMapStyle();
1261
1262        var mapElement = $(
1263            ".projects-map-graphic #" + $(this).parent().attr("data-name")
1264        );
1265
1266        // Mariestad constist of several paths
1267        if (mapElement.attr("id") == "Mariestad") {
1268            var subElements = mapElement.find(".map-item");
1269            subElements.css({ fill: selectedColor });
1270            mapElement.find(".text").toggle();
1271
1272            subElements.get().forEach(function (element) {
1273                addClass(element, "map-item-selected");
1274            });
1275        } else {
1276            mapElement.css({ fill: selectedColor });
1277            addClass(mapElement, "map-item-selected");
1278            mapElement.next(".text").toggle();
1279        }
1280    });
1281
1282    // CATEGORY LIST - CLICK
1283    $(".categories-filter a").on("click", function (e) {
1284        e.preventDefault();
1285
1286        var li = $(this).parent();
1287        var id = li.attr("data-id");
1288        var name = li.attr("data-name");
1289
1290        setSelected(li);
1291
1292        $(".filter-menu-links a").removeClass("filter-menu-selected");
1293        $(this).addClass("filter-menu-selected");
1294
1295        filterListBySelector(".filter-cat-" + id);
1296        setListingHeader(listingHeadingFormat.format("inom " + name));
1297
1298        clearMapStyle();
1299
1300        $(".projects-map-graphic .filter-cat-" + id)
1301            .get()
1302            .forEach(function (element) {
1303                $(element).css({ fill: selectedColor });
1304                addClass(element, "map-item-selected");
1305                $(element).next(".text").toggle();
1306            });
1307
1308        if (googleMapsIsEnabled()) {
1309            // Google map filter
1310            map.getZoom() < 16 ? (zoomLevel = 1) : (zoomLevel = 2);
1311            var catId = parseInt(id);
1312            for (var i = 0; i < markers.length; i++) {
1313                if (!markers[i].categories.includes(catId)) {
1314                    markers[i].marker.setVisible(false);
1315                } else {
1316                    markers[i].marker.setIcon(null);
1317
1318                    if (zoomLevel === 2) {
1319                        markers[i].marker.setIcon(markers[i].bigIcon);
1320                    } else {
1321                        markers[i].marker.setIcon(markers[i].defaultIcon);
1322                    }
1323
1324                    markers[i].marker.setVisible(true);
1325                }
1326            }
1327
1328            google.maps.event.trigger(map, "resize");
1329        }
1330    });
1331
1332    // MUNICIPALITIES LIST - HOVER
1333    $(".municipalities-filter a").hover(
1334        // ON HOVER ENTER
1335        function () {
1336            munListHover($(this), hoverColor, "pointer");
1337        },
1338
1339        // ON HOVER LEAVE
1340        function () {
1341            munListHover($(this), defaultColor, "default");
1342        }
1343    );
1344
1345    // CATEGORIES LIST - HOVER
1346    $(".categories-filter a").hover(
1347        // ON HOVER ENTER
1348        function () {
1349            colorMapElements($(this).parent().attr("data-id"), hoverColor);
1350        },
1351
1352        // ON HOVER LEAVE
1353        function () {
1354            colorMapElements($(this).parent().attr("data-id"), defaultColor);
1355        }
1356    );
1357
1358    // MAP - HOVER
1359    $(".projects-map-graphic .map-item").hover(
1360        // ON HOVER ENTER
1361        function () {
1362            mapHover(this, hoverColor, "pointer", true);
1363        },
1364        // ON HOVER LEAVE
1365        function () {
1366            mapHover(this, defaultColor, "default", false);
1367        }
1368    );
1369
1370    // MAP - CLICK
1371    $(".projects-map-graphic .map-item").on("click", function (e) {
1372        e.preventDefault();
1373
1374        clearMapStyle();
1375
1376        var name = $(this).attr("id"); // Name of the municipality
1377
1378        // Mariestad hack
1379        if (name.indexOf("Mariestad") > -1) {
1380            name = "Mariestad";
1381        }
1382
1383        var municipalityItem = $(
1384            ".municipalities-filter " + "li[data-name='" + name + "']"
1385        ).find("a");
1386
1387        if (municipalityItem.length > 0) municipalityItem.click(); // Lazy me
1388    });
1389
1390    // MUNICIPALITIES (MOBILE) - ON CHANGE
1391    $("#municipalities-filter-mobile").on("change", function () {
1392        var id = $("#municipalities-filter-mobile option")
1393            .filter(":selected")
1394            .val();
1395        var name = $("#municipalities-filter-mobile option")
1396            .filter(":selected")
1397            .text();
1398
1399        if (id == "-1") {
1400            $("#categories-filter-mobile").val("-1");
1401            $("#municipalities-filter-mobile").val("-1");
1402            filterListBySelector(".list-item");
1403            setListingHeader(listingHeadingFormat.format("i Skaraborg "));
1404            return;
1405        }
1406
1407        $("#categories-filter-mobile").val("-1");
1408
1409        filterListBySelector(".filter-mun-" + id);
1410        setListingHeader(listingHeadingFormat.format("i " + name));
1411    });
1412
1413    // CATEGORIES (MOBILE) - ON CHANGE
1414    $("#categories-filter-mobile").on("change", function () {
1415        var id = $("#categories-filter-mobile option").filter(":selected").val();
1416        var name = $("#categories-filter-mobile option").filter(":selected").text();
1417
1418        if (id == "-1") {
1419            $("#categories-filter-mobile").val("-1");
1420            $("#municipalities-filter-mobile").val("-1");
1421            filterListBySelector(".list-item");
1422            setListingHeader(listingHeadingFormat.format("i Skaraborg "));
1423            return;
1424        }
1425
1426        $("#municipalities-filter-mobile").val("-1");
1427
1428        filterListBySelector(".filter-cat-" + id);
1429        setListingHeader(listingHeadingFormat.format("inom " + name));
1430    });
1431
1432    // FILTER ALL - CLICK
1433    $(".reset-filter").on("click", function (e) {
1434        e.preventDefault();
1435
1436        setParameter("cat", "");
1437        setParameter("t", "");
1438
1439        // Desktop
1440        clearMapStyle();
1441        clearFilter();
1442        filterListBySelector(".list-item");
1443        setListingHeader(
1444            listingHeadingFormat.format(projectMapSettings.listingHeadingDefaultText)
1445        );
1446
1447        // Mobile
1448        $("#categories-filter-mobile").val("-1");
1449        $("#municipalities-filter-mobile").val("-1");
1450
1451        if (googleMapsIsEnabled()) {
1452            // Google map
1453            for (var i = 0; i < markers.length; i++) {
1454                markers[i].marker.setVisible(true);
1455                markers[i].marker.setIcon(markers[i].defaultIcon);
1456            }
1457        }
1458    });
1459
1460    let filterId = getParameterByName("cat");
1461    if (filterId) {
1462        let activeTab = getParameterByName("t");
1463        if (activeTab.length) {
1464            if (activeTab === "tabs-1") {
1465                $("#categories-filter-mobile").val(filterId);
1466                $("#municipalities-filter-mobile").val("-1");
1467            } else if (activeTab === "tabs-2") {
1468                $("#municipalities-filter-mobile").val(filterId);
1469                $("#categories-filter-mobile").val("-1");
1470            }
1471            
1472            $("a[href=#" + activeTab + "]").trigger( "click");
1473        }
1474
1475        let li = $("li[data-id=" + filterId + "]");
1476        let filterLink = li.children("a");
1477        if (!filterLink.length) {
1478            return;
1479        }
1480
1481        if (googleMapsIsEnabled()) {
1482            google.maps.event.addListenerOnce(map, "idle", function () {
1483                filterLink.trigger("click");
1484            });
1485        } else {
1486            filterLink.trigger("click");
1487        }
1488    }
1489
1490    /* 
1491      ==================================================
1492      Datepicker
1493      ================================================== 
1494      */
1495    var dayNamesShort = ["Mån", "Tis", "Ons", "Tors", "Fre", "Lör", "Sön"];
1496    var monthNames = [
1497        "Januari",
1498        "Februari",
1499        "Mars",
1500        "April",
1501        "Maj",
1502        "Juni",
1503        "Juli",
1504        "Augusti",
1505        "September",
1506        "Oktober",
1507        "November",
1508        "December",
1509    ];
1510    function format(dt) {
1511        return (
1512            Picker.prototype.pad(dt.getDate()) +
1513            " " +
1514            monthNames[dt.getMonth()].slice(0, 3) +
1515            " " +
1516            dt.getFullYear()
1517        );
1518    }
1519
1520    var datepicker = function (root) {
1521        "use strict";
1522
1523        var icon =
1524            '<svg viewBox="0 0 512 512"><polygon points="268.395,256 134.559,121.521 206.422,50 411.441,256 206.422,462 134.559,390.477 "/></svg>';
1525        var dateInput = $(root).siblings("#date")[0];
1526        var altInput = $(root).siblings("#alt")[0];
1527        var calendarBlock = $(root).closest(".EventCalendarBlock")[0];
1528
1529        var doc = document.documentElement;
1530
1531        function show() {
1532            root.removeAttribute("hidden");
1533        }
1534
1535        function hide() {
1536            root.setAttribute("hidden", "");
1537            doc.removeEventListener("click", hide);
1538        }
1539
1540        function onSelectHandler() {
1541            var value = this.get();
1542            if (value.start) {
1543                dateInput.value = value.start.Ymd();
1544                altInput.value = format(value.start);
1545                hide();
1546
1547                var e = document.createEvent("HTMLEvents");
1548                e.initEvent("oninput", false, true);
1549                calendarBlock.dispatchEvent(e);
1550            }
1551        }
1552
1553        var picker = new Picker(root, {
1554            min: new Date(dateInput.min),
1555            max: new Date(dateInput.max),
1556            icon: icon,
1557            twoCalendars: false,
1558            dayNamesShort: dayNamesShort,
1559            monthNames: monthNames,
1560            onSelect: onSelectHandler,
1561        });
1562
1563        root.parentElement.addEventListener("click", function (e) {
1564            e.stopPropagation();
1565        });
1566
1567        dateInput.addEventListener("change", function () {
1568            if (dateInput.value) {
1569                picker.select(new Date(dateInput.value));
1570            } else {
1571                picker.clear();
1572            }
1573        });
1574
1575        altInput.addEventListener("focus", function () {
1576            altInput.blur();
1577            show();
1578            doc.addEventListener("click", hide, false);
1579        });
1580        return picker;
1581    };
1582
1583    //CalendarTileBlock Functions
1584
1585    //CalendarBlock Functions
1586
1587    var jsonPostObjectTemplate = {
1588        IncludeContent: true,
1589        SearchTypes: "Event",
1590        Skip: 0,
1591        Site: 5428,
1592        Sort: "Date",
1593    };
1594
1595    var months = [
1596        "Jan",
1597        "Feb",
1598        "Mar",
1599        "Apr",
1600        "Maj",
1601        "Jun",
1602        "Jul",
1603        "Aug",
1604        "Sep",
1605        "Okt",
1606        "Nov",
1607        "Dec",
1608    ];
1609
1610    $(".calendar-tile-block").each(function (index) {
1611        var element = $(this);
1612        var loadingElement = element.find(".calendar-loader");
1613        var eventsContainer = element.find(".events");
1614        var jsonPostObject = jsonPostObjectTemplate;
1615        var take = element.data("take");
1616        var openInDetailsPage = element.data("detailpage");
1617        var detailsPageUrl = element.data("detailspageurl");
1618
1619        var baseUrl = element.data("baseurl");
1620        var eventRoute = element.data("route");
1621
1622        loadingElement.toggle();
1623
1624        jsonPostObject.Take = take;
1625
1626        if (element.data("tags") !== "") {
1627            jsonPostObject.Tags = element.data("tags");
1628        }
1629        if (element.data("config") !== "") {
1630            jsonPostObject.Settings = element.data("config");
1631        }
1632        jsonPostObject.Date = new Date();
1633
1634        $.ajax({
1635            url: baseUrl + eventRoute,
1636            data: jsonPostObject,
1637            dataType: "json",
1638            method: "Post",
1639            success: function (response) {
1640                var result = "";
1641
1642                response.Hits.forEach(function (hit) {
1643                    var startDate = new Date(hit.Start);
1644                    var endDate = new Date(hit.End);
1645                    var dateString = "";
1646
1647                    if ((startDate.getDay() && startDate.getMonth()) != (endDate.getDay() && endDate.getMonth())) {
1648                        if (startDate.getMonth() != endDate.getMonth()) {
1649                            dateString = startDate.getDate() + ' ' + months[startDate.getMonth()] + ' - ' + endDate.getDate() + ' ' + months[endDate.getMonth()];
1650                        } else {
1651                            dateString = startDate.getDate() + ' - ' + endDate.getDate() + ' ' + months[endDate.getMonth()];
1652                        }
1653                    } else {
1654                        dateString = startDate.getDate() + ' ' + months[startDate.getMonth()];
1655                    }
1656
1657                    var linkUrl = "";
1658                    if (openInDetailsPage === "true" || openInDetailsPage === "True") {
1659                        linkUrl = detailsPageUrl + "?event=" + hit.Id;
1660                    } else {
1661                        linkUrl = baseUrl + hit.Url;
1662                    }
1663
1664                    result += [
1665                        '<a href="' + linkUrl + '"  class="event">',
1666                        '<div class="date">' +
1667                        dateString +
1668                        '</div>',
1669                        '<div class="event-heading"><span>' + hit.Heading + "</span></div>",
1670                        "</a>",
1671                    ].join("\n");
1672                });
1673                loadingElement.toggle();
1674                eventsContainer.append(result);
1675            },
1676        });
1677    });
1678
1679    $(".EventCalendarBlock").each(function (index) {
1680        var element = $(this);
1681        var datepickerelem = element.find("#picker");
1682
1683        var picker;
1684        if (datepickerelem) {
1685            picker = datepicker(datepickerelem[0]);
1686            if (picker) {
1687                picker.set(new Date());
1688                picker.select(new Date());
1689            }
1690        }
1691
1692        var calendarHeader = element.find(".EventCalendarHeader");
1693        var calendarFooter = element.find(".EventCalendarFooter");
1694        var calendarFilter = element.find(".EventCalendarFilter");
1695        var calendarList = element.find(".EventCalendarList");
1696        var loadingElement = element.find(".calendar-loader");
1697
1698        var startDateElement = calendarHeader.find(".start-date");
1699
1700        var showMore = calendarFooter.find("#calendar-next-page");
1701
1702        var searchButton = calendarFilter.find(".button");
1703
1704        var clearFilters = calendarHeader.find(".clear-filters");
1705        var totalHitsElement = calendarHeader.find(".total-hits");
1706        var totalShowingElement = calendarHeader.find(".showing");
1707        var showingQuery = calendarHeader.find(".query");
1708
1709        var loadingClass = "calender-loading";
1710
1711        var jsonPostObject = jsonPostObjectTemplate;
1712        var take = element.data("take");
1713
1714        jsonPostObject.Take = take;
1715
1716        if (element.data("tags") !== "") {
1717            jsonPostObject.Tags = element.data("tags");
1718        }
1719        if (element.data("config") !== "") {
1720            jsonPostObject.Settings = element.data("config");
1721        }
1722
1723        jsonPostObject.ImageSize = { Crop: true, height: 400, width: 400 };
1724
1725        var readMoreTranslation = element.data("readmore");
1726        var searchField = element.find("#calendar-search");
1727        var baseUrl = element.data("baseurl");
1728        var eventRoute = element.data("route");
1729        var openInDetailsPage = element.data("detailpage");
1730        var detailsPageUrl = element.data("detailspageurl");
1731
1732        var toggleLoadingState = function () {
1733            calendarList.toggleClass(loadingClass);
1734            loadingElement.toggle();
1735        };
1736
1737        var sendRequest = function () {
1738            toggleLoadingState();
1739            if (searchField.val() && searchField.val().length > 0) {
1740                jsonPostObject.Query = searchField.val();
1741            } else {
1742                jsonPostObject.Query = "";
1743            }
1744            showingQuery.html(jsonPostObject.Query);
1745            var tempDate = null;
1746            if (picker.get().start) {
1747                tempDate = new Date(picker.get().start);
1748                jsonPostObject.Date = tempDate.toISOString();
1749                jsonPostObject.DayRange = 365;
1750                startDateElement.html(format(tempDate));
1751            } else {
1752                tempDate = new Date(new Date());
1753                jsonPostObject.Date = tempDate.toISOString();
1754                jsonPostObject.DayRange = 365;
1755                startDateElement.html(format(tempDate));
1756            }
1757
1758            $.ajax({
1759                url: baseUrl + eventRoute,
1760                data: jsonPostObject,
1761                dataType: "json",
1762                method: "Post",
1763                success: function (response) {
1764                    var result = "";
1765                    totalHitsElement.text(response.TotalCount);
1766                    totalShowingElement.text(response.Hits.length);
1767                    response.Hits.forEach(function (hit) {
1768                        var tmpDescElement = document.createElement("DIV");
1769                        tmpDescElement.innerHTML = hit.Description;
1770                        var desc =
1771                            tmpDescElement.textContent || tmpDescElement.innerText || "";
1772
1773                        if (desc.length > 200) {
1774                            desc = desc.slice(0, 200);
1775                            desc += "...";
1776                        }
1777
1778                        var startDate = new Date(hit.Start);
1779                        var endDate = new Date(hit.End);
1780                        var today = new Date(jsonPostObject.Date);
1781                        var date = startDate >= today ? startDate : today;
1782                        var endDate = new Date(hit.End);
1783
1784                        hit.Dates = hit.Dates.filter(function (d) {
1785                            return new Date(d.Date) >= today;
1786                        }).sort(function (a, b) {
1787                            return new Date(a.Date) - new Date(b.Date);
1788                        });
1789
1790                        if (hit.Dates[0] != undefined) {
1791                            date = new Date(hit.Dates[0].Date);
1792                        }
1793
1794                        var formattedDate = formatDate(date);
1795                        var startAndEndDate = "";
1796                        if ((startDate.getDate() && startDate.getMonth()) == (endDate.getDate() && endDate.getMonth())) {
1797                            startAndEndDate += [
1798                                '<div class="only-start-date">' +
1799                                '<div class="start-date">' +
1800                                '<span class="day">' +
1801                                startDate.getDate() +
1802                                '</span>' +
1803                                '<span class="month">' +
1804                                months[endDate.getMonth()] +
1805                                '</span>' +
1806                                '</div>' +
1807                                '</div>',
1808                            ];
1809                        } else {
1810                            startAndEndDate += [
1811                                '<div class="start-end-date">' +
1812                                '<div class="start-date">' +
1813                                '<span class="day">' +
1814                                startDate.getDate() +
1815                                '</span>' +
1816                                '<span class="month">' +
1817                                months[startDate.getMonth()] +
1818                                '</span>' +
1819                                '</div>' +
1820                                '<span class="hyphen">-</span>' +
1821                                '<div class="end-date">' +
1822                                '<span class="day">' +
1823                                endDate.getDate() +
1824                                '</span>' +
1825                                '<span class="month">' +
1826                                months[endDate.getMonth()] +
1827                                '</span>' +
1828                                '</div>' +
1829                                '</div>'
1830                            ];
1831                        }
1832
1833                        var linkTo = ""
1834                        if (openInDetailsPage === "true" || openInDetailsPage === "True") {
1835                            linkTo += ['<a href="' + detailsPageUrl + '?event=' + hit.Id + '" class="external-link">' +
1836                                '<span class="internal-link">' + readMoreTranslation + "</span>" +
1837                                "</a>"]
1838                        } else {
1839                            linkTo += ['<a href="' + baseUrl + hit.Url + '" class="external-link">' +
1840                                "<span>" + readMoreTranslation + "</span>" +
1841                                '<i class="fas fa-external-link-alt"></i>' +
1842                                "</a>"]
1843                        }
1844
1845                        result += [
1846                            '<div class="EventCalendarItem">',
1847                            '<div class="inner">',
1848                            '<div class="image">',
1849                            '<img alt="' +
1850                            hit.Heading +
1851                            '" title="' +
1852                            hit.Heading +
1853                            '" src="' +
1854                            hit.Image.Path +
1855                            '">',
1856                            startAndEndDate +
1857                            '</div >',
1858                            '<div class="text">',
1859                            '<div class="date">' + formattedDate + "</div>",
1860                            '<h3 class="heading">' + hit.Heading + "</h3>",
1861                            '<p class="intro">' + desc + "</p>",
1862                            '<div class="actions">' +
1863                            linkTo +
1864                            "</div>",
1865                            "</div >",
1866                            "</div >",
1867                            "</div>",
1868                        ].join("\n");
1869                    });
1870                    if (response.Hits.length === response.TotalCount) {
1871                        showMore.hide();
1872                    } else {
1873                        showMore.show();
1874                    }
1875                    calendarList.append(result);
1876                    toggleLoadingState();
1877                },
1878            });
1879        };
1880        var submit = function (e) {
1881            if (e !== undefined) {
1882                if (e.keyCode === 13) {
1883                    e.stopPropagation();
1884                    e.preventDefault();
1885                    calendarList.html("");
1886                    jsonPostObject.Skip = 0;
1887                    sendRequest();
1888                } else if (e.keyCode === undefined) {
1889                    calendarList.html("");
1890                    jsonPostObject.Skip = 0;
1891                    sendRequest();
1892                }
1893            } else {
1894                calendarList.html("");
1895                jsonPostObject.Skip = 0;
1896                sendRequest();
1897            }
1898        };
1899
1900        clearFilters.on("click", function (e) {
1901            calendarList.html("");
1902            jsonPostObject.Skip = 0;
1903            searchField.val("");
1904            jsonPostObject.Date = new Date();
1905            picker.select(jsonPostObject.Date);
1906            picker.set(jsonPostObject.Date);
1907            sendRequest();
1908        });
1909        showMore.on("click", function (e) {
1910            jsonPostObject.Skip += jsonPostObject.Take;
1911            sendRequest();
1912        });
1913
1914        searchField.on("keydown", submit);
1915        element.on("oninput", submit);
1916        searchButton.on("click", submit);
1917        sendRequest();
1918    });
1919
1920    function formatDate(date) {
1921        var d = new Date(date),
1922            month = "" + (d.getMonth() + 1),
1923            day = "" + d.getDate(),
1924            year = d.getFullYear();
1925
1926        if (month.length < 2) month = "0" + month;
1927        if (day.length < 2) day = "0" + day;
1928
1929        return [year, month, day].join("-");
1930    }
1931});
1932
1933/* Search Page */
1934$(document).ready(function () {
1935    if ($("#normalResult").length > 0) {
1936        if ($(self.window).width() <= 479) {   //use antoher icon in mobile mode
1937            $("[rel='next']").empty().html("»")
1938            $("[rel='prev']").empty().html("«")
1939        }
1940        else {
1941            $("[rel='next']").empty().html("Nästa »")
1942            $("[rel='prev']").empty().html("« Föregående")
1943        }
1944
1945        $("[rel='next']").add("[rel='prev']").addClass("customesspaging")
1946
1947        $("[rel='next']").add("[rel='prev']").hover(
1948            function () {
1949                $(this).css("background-color", "#E50052");
1950                $(this).css("color", "#FFF");
1951            }, function () {
1952                $(this).css("background-color", ""); //to remove property set it to ''
1953                $(this).css("color", "#000");
1954            }
1955        );
1956    }
1957});
1958
1959/*Cookiebot event handlers*/
1960$(function () {
1961    window.addEventListener('CookiebotOnAccept', function (e) {
1962        if (Cookiebot.consent.statistics) {
1963            $vizzit.cookie.set();
1964        }
1965    }, false);
1966});
1967
1968/* Rek ai autocomplete */
1969$(function () {
1970    var scriptTag = document.querySelector('script[src="https://static.rekai.se/addon/rekai_autocomplete.min.js"]');
1971    if (scriptTag != null) {
1972        var rekAutocomplete = rekai_autocomplete('.SearchTfd', {
1973            clearOnSelected: true,
1974            styled: true,
1975            highlight: true,
1976        },
1977            [{
1978                templates: {
1979                    suggestion: function (suggestion, dataset) {
1980                        // If news article
1981                        if (suggestion.url.indexOf('http') == 0) {
1982                            var boldText = highlightWord(suggestion.title, dataset);
1983                            return '<p class="search-page-normal"><a href="' + suggestion.url + '"><span>' + boldText + '</span></a></p>';;
1984                        }
1985                        else { // Else render normaly
1986                            var boldText = highlightWord(suggestion.title, dataset);
1987                            return '<p class="search-page-normal">' + boldText + '</p>';
1988                        }
1989                    }
1990                }
1991            }]
1992        ).on('rekai_autocomplete:selected', function (event, suggestion, dataset) {
1993            if (suggestion.url.indexOf('http') == 0) {
1994                window.location = suggestion.url;
1995            }
1996            window.location = '/Sokresultat?query=' + encodeURIComponent(suggestion.title);
1997        }).on('rekai_autocomplete:updated ', function (event) {
1998            var dropdownMenus = document.querySelectorAll(".rekai-dropdown-menu");
1999            dropdownMenus.forEach(function (Menu) {
2000                Menu.style.width = Math.round(document.body.clientWidth * 0.15) + "px"
2001            })
2002        });
2003    }
2004})
2005function highlightWord(text, query) {
2006    // Create a case-insensitive regular expression
2007    let regex = new RegExp(`(${query})`, 'gi');
2008    // Replace the matching text with bold text
2009    return text.replace(regex, '<b>$1</b>');
2010}
2011
2012/* FacilityOpenHours block */
2013$(document).ready(function () {
2014    $('.facility-opening-hours .previous-week').on('click', (e) => {
2015        e.preventDefault();
2016        var targetContainer = $(e.target).closest('.facility-opening-hours');
2017        if ($(targetContainer).find('.next-week').hasClass('hidden')) {
2018            $(targetContainer).find('.next-week').removeClass('hidden');
2019        }
2020        var elements = $(targetContainer).find('.week-day-list').get().reverse();
2021        var startElement = -1;
2022        var endElement = -1;
2023        for (var i = 0; i < elements.length; i++) {
2024            if (!$(elements[i]).hasClass('hidden')) {
2025                $(elements[i]).addClass('hidden');
2026                $(elements[i]).removeClass('active');
2027                
2028                if (startElement === -1) {
2029                    startElement = i + 7;
2030                    endElement = startElement + 6;
2031                }
2032            }
2033
2034            if (i >= startElement && i <= endElement) {
2035                $(elements[i]).removeClass('hidden');
2036                $(elements[i]).addClass('active');
2037            }
2038        }
2039
2040        if (startElement === (elements.length - 7)) {
2041            $(targetContainer).find('.previous-week').addClass('hidden');
2042            return
2043        }
2044    })
2045
2046    $('.facility-opening-hours .next-week').on('click', (e) => {
2047        e.preventDefault();
2048        var targetContainer = $(e.target).closest('.facility-opening-hours');
2049        if ($(targetContainer).find('.previous-week').hasClass('hidden')) {
2050            $(targetContainer).find('.previous-week').removeClass('hidden');
2051        }
2052
2053        var elements = $(targetContainer).find('.week-day-list');
2054        var startElement = -1;
2055        var endElement = -1;
2056        var x = 1;
2057        for (var i = 0; i < elements.length; i++) {
2058
2059            if (!$(elements[i]).hasClass('hidden')) {
2060                $(elements[i]).addClass('hidden');
2061                $(elements[i]).removeClass('active');
2062                if (startElement === -1) {
2063                    startElement = i + 7;
2064                    endElement = startElement + 6;
2065                }
2066            }
2067
2068            if (i >= startElement && i <= endElement) {
2069                $(elements[i]).removeClass('hidden');
2070                $(elements[i]).addClass('active'+ x +'');
2071                x++;
2072            }
2073        }
2074
2075        if ( endElement === (elements.length - 1)) {
2076            $(targetContainer).find('.next-week').addClass('hidden');
2077            return
2078        }
2079    })
2080
2081});
2082
2083/* Accordion trigger */
2084$(document).ready(function () {
2085    if ($(".Accordion-trigger").length > 0)
2086    {
2087        $(".Accordion-trigger").on('click', function (e) {
2088            if ($(e.target).attr("aria-expanded") == "false") {
2089                $(e.target).parent().find(".accordion-extenstion").addClass("expanded");
2090
2091            } else {
2092                setTimeout(() => {
2093                        $(e.target).parent().find(".accordion-extenstion").delay(1500).removeClass("expanded")
2094                    },
2095                    599);
2096            }
2097        })
2098    }    
2099});

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.