PageSourceSearch

https://besikta.se/static/js/bundle.js?v=639266842882845523%20defer

js besikta.se collected 2026-10-04 05:42:37 UTC 41,903 bytes, 1,016 lines download raw bytes

1$(document).on('click', '.open-trailer-alert', {}, function (e) {
2
3	e.preventDefault();
4	var $alert = $("#traileralert");
5	$alert.fadeIn(150);
6	$alert.find(".alert-edit-form").addClass("open");
7	$("body").addClass("alert-open");
8});
9
10$(document).on('click', '.change-reg', {}, function (e) {
11
12    e.preventDefault();
13    var $alert = $("#changeregalert");
14    $alert.fadeIn(150);
15    $alert.find(".alert-edit-form").addClass("open");
16    $("body").addClass("alert-open");
17});
18
19$(document).on('click', '.open-login-alert', {}, function (e) {
20	e.preventDefault();
21	var $alert = $("#loginalert");
22	$alert.fadeIn(150);
23	$alert.find(".alert-edit-form").addClass("open");
24    $("body").addClass("alert-open");
25
26});
27
28$(document).on('click', '.add-vehicle-open', {}, function (e) {
29
30    e.preventDefault();
31    var $alert = $("#addvehiclealert");
32    $alert.fadeIn(150);
33    $alert.find(".alert-edit-form").addClass("open");
34    $("body").addClass("alert-open");
35});
36
37$(document).on('click', '.pickstation', {}, function (e) {
38
39    e.preventDefault();
40    var $alert = $("#mapoverlay");
41    $alert.fadeIn(150);
42    $alert.find(".alert-edit-form").addClass("open");
43    $("body").addClass("alert-open");
44    initMap();
45    $(document).on("keydown", function (keyEvent) {
46        if (keyEvent.key === "Escape") {
47            closeAlert();
48        }
49    });
50});
51
52$(document).on('click', '.close-alert', {}, function (e) {
53	e.preventDefault();
54	closeAlert();
55});
56
57function closeAlert() {
58	$(".alert-edit-form").removeClass("open");
59	$("body").removeClass("alert-open");
60	$(".alert").fadeOut(200);
61}
62
63$(document).ready(function () {
64    $("[data-type='bw-modal']").on("click", function (e) {
65        e.preventDefault();
66        const $this = $(this);
67        const $modal = $("#generalmodal");
68        $modal.find(".bw-modal-body-content").html($this.next().html());
69        $modal.fadeIn(150);
70        $modal.find(".bw-modal-body").addClass("open");
71        $modal.trigger("opened");
72        $("body").addClass("bw-modal-open");
73
74        $modal.find(".bw-modal-close").one("click", function () {
75            closeModal($modal);
76        });
77        $modal.on("click", function (clickEvent) {
78            if ($(clickEvent.target).hasClass("bw-modal")) {
79                closeModal($modal);
80            }
81        });
82        $(document).on("keydown", function (keyEvent) {
83            if (keyEvent.key === "Escape") {
84                closeModal($modal);
85            }
86        });
87    });
88
89    const closeModal = function (modal) {
90        modal.fadeOut(250);
91        modal.find(".bw-modal-body").removeClass("open");
92        $("body").removeClass("bw-modal-open");
93    };
94});
95
96/*Start of portal recurring timeslots*/
97
98$(document).on('click', '.send-email-open', {}, function (e) {
99    e.preventDefault();
100    const $this = $(this);
101    var $alert = $("#sendemailalert");
102    $alert.fadeIn(150);
103    $alert.find(".alert-edit-form").addClass("open");
104    $("body").addClass("alert-open");
105    $("#currentStation").val($this.data('station'));
106    $("#currentDate").val($this.data('bookingdate'));
107});
108
109//$(document).on('click', '#sendemailalert', {}, function (e) {
110//    e.preventDefault();
111//    $(".alert-edit-form").removeClass("open");
112//    $("body").removeClass("alert-open");
113//    $("#currentStation").val('');
114//    $("#currentDate").val('');
115//    $("#alertmail").val('');
116//    $("#addregrerror").html("");
117//    $(".alert").fadeOut(200);
118//});
119
120$(document).on('click', '.close-alert', {}, function (e) {
121    e.preventDefault();
122    $(".alert-edit-form").removeClass("open");
123    $("body").removeClass("alert-open");
124    $("#currentStation").val('');
125    $("#currentDate").val('');
126    $("#alertmail").val('');
127    $("#alerttext").val('');
128    $("#addregrerror").html("");
129    $(".alert").fadeOut(200);
130    $(".booking-mail-wrapper").removeClass("hidden");
131    $(".portal-button-wrapper").removeClass("hidden");
132});
133
134$(".send-mail-button").on("click", function (e) {
135    var $this = $(this);
136    $("#addregrerror").html("");
137    if (!$this.hasClass("disabled")) {
138        if (isValidEmailAddress($("#alertmail").val())) {
139            if ($("#alerttext").val().length < 251) {
140                $("#alertmail").attr("disabled", "disabled");
141                $("#loading").addClass("show");
142                $this.addClass("disabled");
143                $.ajax({
144                    contentType: "application/json; charset=utf-8",
145                    dataType: "json",
146                    url: "/PortalRecurringPage/SendEmail?email=" + $("#alertmail").val() + "&station=" + $("#currentStation").val() + "&time=" + $("#currentDate").val() + "&message=" + $("#alerttext").val(),
147                    type: "GET",
148                    cache: false,
149                    success: function (data) {
150                        if (data.success === true) {
151                            $("#loading").removeClass("show");
152                            $("#addregrerror").append("<div class=\"success margin-top-xl\">Ditt email är nu skickat.</div>");
153                            $this.removeClass("disabled");
154                            $("#alertmail").removeAttr("disabled");
155                            $(".booking-mail-wrapper").addClass("hidden");
156                            $(".portal-button-wrapper").addClass("hidden");
157                        } else {
158                            $("#loading").removeClass("show");
159                            $("#addregrerror").append("<div class=\"error margin-top\">NÃ¥got gick fel. Kunde inte skicka ditt email.</div>");
160                            $this.removeClass("disabled");
161                            $("#alertmail").removeAttr("disabled");
162                        }
163                    },
164                    error: function () {
165                    }
166                });
167            } else {
168                $("#addregrerror").append("<div class=\"error margin-bottom\"><strong>\"" +
169                    $("#alerttext").val().length +
170                    "\"</strong>/250 tecken.</div>");
171            }
172        } else {
173            $("#addregrerror").append("<div class=\"error margin-bottom\"><strong>\"" +
174                $("#alertmail").val() +
175                "\"</strong> är ingen giltigt email</div>");
176
177            $this.removeClass("disabled");
178            $("#alertmail").removeAttr("disabled");
179        }
180    }
181});
182
183/*End of portal recurring timeslots*/
184/* 
185Initializes and manages a custom scrollbar: 
186updates handle size, 
187synchronizes handle movement with content scrolling, 
188supports drag - and - click operations, 
189and accommodates both mouse and touch inputs for a responsive user experience.
190*/
191$(document).ready(function () {
192    fixBrokenStationScrollContainer();
193
194    $('.scrollable-area').each(function () {
195        const scrollContent = $(this).find('.scroll-content');
196        const customHandle = $(this).find('.custom-handle');
197        const customScrollbar = $(this).find('.custom-scrollbar');
198
199        if (!scrollContent || !customHandle || !customScrollbar) {
200            return;
201        }
202
203        function updateHandleWidth() {
204            if (!scrollContent || !customScrollbar) {
205                return;
206            }
207
208            const ratio = scrollContent.outerWidth() / scrollContent.get(0).scrollWidth;
209            const handleWidth = ratio * customScrollbar.outerWidth();
210            customHandle.css('width', `${handleWidth}px`);
211        }
212
213        function syncScroll() {
214            if (!scrollContent || !customHandle || !customScrollbar) {
215                return;
216            }
217
218            const scrollRatio = scrollContent.get(0).scrollLeft / (scrollContent.get(0).scrollWidth - scrollContent.outerWidth());
219            const handlePosition = scrollRatio * (customScrollbar.outerWidth() - customHandle.outerWidth());
220            customHandle.css('left', `${handlePosition}px`);
221        }
222
223        function startDrag(e) {
224            if (!customHandle || !customScrollbar) {
225                return;
226            }
227
228            // Determine if it's a touch event or a mouse event and set the starting point accordingly
229            const startX = e.type === 'touchstart' ? e.touches[0].pageX : e.pageX;
230
231            const handleRect = customHandle.get(0).getBoundingClientRect();
232            const scrollbarRect = customScrollbar.get(0).getBoundingClientRect();
233            const maxScrollLeft = scrollContent.get(0).scrollWidth - scrollContent.outerWidth();
234            let startLeft = handleRect.left - scrollbarRect.left;
235
236            function onMove(e) {
237            // Determine if it's a touch event or a mouse event and set the current point accordingly
238                const currentX = e.type === 'touchmove' ? e.touches[0].pageX : e.pageX;
239                const dx = currentX - startX;
240                const newLeft = Math.min(Math.max(0, startLeft + dx), customScrollbar.outerWidth() - handleRect.width);
241                const scrollRatio = newLeft / (customScrollbar.outerWidth() - handleRect.width);
242                scrollContent.get(0).scrollLeft = scrollRatio * maxScrollLeft;
243            }
244
245            function onEnd() {
246                if (document) {
247                    document.removeEventListener('mousemove', onMove);
248                    document.removeEventListener('mouseup', onEnd);
249                    document.removeEventListener('touchmove', onMove);
250                    document.removeEventListener('touchend', onEnd);
251                }
252            }
253
254            if (document) {
255                document.addEventListener(e.type === 'touchstart' ? 'touchmove' : 'mousemove', onMove);
256                document.addEventListener(e.type === 'touchstart' ? 'touchend' : 'mouseup', onEnd);
257            }
258        }
259
260        function handleScrollbarClick(e) {
261            if (!customHandle || !customScrollbar) {
262                return;
263            }
264
265            console.log('handleScrollbarClick');
266            console.log('e:', e);
267            console.log('customHandle:', customHandle);
268            console.log('customScrollbar:', customScrollbar);
269
270            // Avoid clicks on the handle
271            if (e.target === customHandle) {
272                console.log('Clicked on the handle');
273                return;
274            }
275
276            const targetRect = customScrollbar.get(0).getBoundingClientRect();
277            const handleRect = customHandle.get(0).getBoundingClientRect();
278            const clickPosition = ((e.pageX || e.touches[0].pageX) - targetRect.left) - (handleRect.width / 2); // Center the handle on the click
279            const maxPosition = targetRect.width - handleRect.width;
280            const newPosition = Math.min(Math.max(0, clickPosition), maxPosition);
281            const scrollRatio = newPosition / maxPosition;
282            const maxScrollLeft = scrollContent.get(0).scrollWidth - scrollContent.outerWidth();
283            scrollContent.scrollLeft = scrollRatio * maxScrollLeft;
284        }
285
286        updateHandleWidth();
287        window.addEventListener('resize', updateHandleWidth);
288        scrollContent.on('scroll', syncScroll);
289        customHandle.on('mousedown', startDrag);
290        customHandle.on('touchstart', startDrag, { passive: true });
291        customScrollbar.on('click', handleScrollbarClick);
292
293    });
294
295    /**
296     * Unwraps .related-container and .custom-scrollbar elements from <strong> elements that may have been added by the CMS.
297    * This is a temporary fix until the CMS is fixed to not add these <strong> elements. We need to investigate WHY it does that to some stations...
298    * TODO: Remove this once the CMS is fixed/investigate
299    */
300
301    function fixBrokenStationScrollContainer() {
302        const relatedContainers = $('.related-container');
303        relatedContainers.each((_i, that) => {
304            if ($(that).parent().is('strong')) {
305                $(that).unwrap();
306            }
307        });
308
309        const $scrollbar = $('.custom-scrollbar');
310
311        if ($scrollbar.parent().is('strong')) {
312            $scrollbar.unwrap();
313        }
314    }
315});
316
317let prevScrollpos = window.pageYOffset;
318let $scrolling = false;
319
320$(document).ready(function () {
321    handleDifferentBrowsers();
322    removeUnscrollableScrollables();
323
324    if (typeof $$epiforms !== 'undefined') {
325        $$epiforms(document).ready(function () {
326            $$epiforms('.EPiServerForms').on('formsSubmitted',
327                function (event) {
328                    // const titleText = $($$epiforms(this).get(0)).children('.Form__Title').text();
329                    const form_name = location.pathname.replaceAll('/', '').replaceAll('-', '_');
330                    const success = event.isSuccess;
331                    const form_id = `${$$epiforms(this).get(0).getAttribute('id')}`;
332                    let error_msg = '';
333
334                    setTimeout(function () {
335                        if (!success) {
336                            error_msg = $('.Form__Element__ValidationError:visible').text();
337                        }
338
339                        window.dataLayer = window.dataLayer || [];
340                        window.dataLayer.push({
341                            event: 'form_submit',
342                            form_name,
343                            form_id, //Unikt id för formuläret, ska alltid vara samma id för samma formulär.
344                            success,
345                            error_msg
346                        });
347                    }, 2000);
348                });
349        });
350    }
351
352    $(window).scroll(function () {
353        stickyHeader();
354    });
355
356    SmoothScroll({ stepSize: 50 });
357
358    $('#reg').on('keypress', stopSpacesInRegNr);
359
360    $('.block-start-products-plate-top-wrapper').matchHeight({
361        byRow: true,
362        property: 'height',
363        target: null,
364        remove: false
365    });
366
367    $('.block-text-on-image-wrapper').matchHeight({
368        byRow: true,
369        property: 'height',
370        target: null,
371        remove: false
372    });
373
374    $('#search404').on('click', function (e) {
375        const searchTerm = $('#input404').val();
376        if(searchTerm.length < 3) { return; }
377
378        window.location= `/sok/?q=${searchTerm}`;
379    });
380
381  $('#show-device-menu').on('click', function (e) {
382    e.preventDefault();
383    const $this = $(this);
384
385        if ($this.hasClass('open')) {
386            $('#main').show();
387            $('body').removeClass('menu-open');
388            $this.removeClass('open');
389            $('.device-header-menu').removeClass('open');
390            $('.zoid-outlet').show();
391        } else {
392            $('#main').hide();
393            $('body').addClass('menu-open');
394            $this.addClass('open');
395            $('.device-header-menu').addClass('open');
396            $('.zoid-outlet').hide();
397        }
398    });
399
400    $('.device-caret').on('click', function (e) {
401        e.preventDefault();
402        const $this = $(this);
403
404        if ($this.hasClass('collapsed')) {
405            $this.removeClass('collapsed');
406            $this.next().addClass('open');
407        } else {
408            $this.addClass('collapsed');
409            $this.next().removeClass('open');
410        }
411    });
412
413    $(document)
414        .on(
415            'mouseenter',
416            '.top-menu-item.has-children, .open > .mega',
417            function (event) {
418                hoverMenu(event, true);
419            }
420        )
421        .on(
422            'mouseleave',
423            '.top-menu-item.has-children, .open > .mega',
424            function (event) {
425                hoverMenu(event, false);
426            }
427        );
428
429    /**
430     * Removes scroll handle of scrollable containers that are not scrollable horizontally.
431     * If an container's scroll width is less than the document's width, the sibling element following its parent is removed
432     * (IE the scroll handle).
433     * It early exits if the first scrollable element has the class 'filters'.
434     */
435    function removeUnscrollableScrollables() {
436        const scrollables = document.querySelectorAll('.scroll-content');
437
438        scrollables.forEach((el) => {
439            const docWidth = el.closest('.bw-container').offsetWidth;
440            if (el.scrollWidth < docWidth && !el.className.includes('filters')) {
441                el.parentElement.nextElementSibling.remove();
442            }
443        });
444    }
445
446    function hoverMenu(event, isInside) {
447        const $menuItem = $(event.currentTarget);
448        const $currentTarget = $(event.relatedTarget);
449        if (isInside || $currentTarget.is('.top-nav, .mega')) {
450            $menuItem.parent().addClass('open');
451            $('#menu-overlay').show();
452            return;
453        }
454        $('#menu-overlay').hide();
455        $menuItem.parent().removeClass('open');
456    }
457
458    $(".mega-menu-toggler").on("click", function (e) {
459        e.preventDefault();
460        const $this = $(this);
461
462        if (!$this.next().hasClass("closed")) {
463            $this.next().addClass("closed");
464            $this.find(".mega-caret").addClass("collapsed");
465        } else {
466            $this.next().removeClass("closed");
467            $this.find(".mega-caret").removeClass("collapsed");
468        }
469    });
470
471    //$("#startblockbookingbutton").on("click", function (e) {
472    //    e.preventDefault();
473    //    var reg = $("#reg").val();
474
475    //    if (isValidRegistrationNumber(reg)) {
476    //        $("#startbookingform").submit();
477    //    } else {
478    //        $("#errorwrapper").html("<div class=\"booking-alert\">Du har angivet ett felaktigt registreringsnummer</div>");
479    //    }
480    //});
481
482    $(".close-global").on("click", function (e) {
483        e.preventDefault();
484        var cookieName = "global-info";
485        document.cookie = cookieName + "=true;path=/";
486        $("#global-info").remove();
487    });
488
489    $("#cookieacceptbutton").on("click", function (e) {
490        e.preventDefault();
491        var aYearFromNow = new Date();
492        aYearFromNow.setFullYear(aYearFromNow.getFullYear() + 1);
493        var dateAsString = aYearFromNow.toUTCString();
494        var cookieName = "cookie-accept";
495        document.cookie = cookieName + "=true; expires=" + dateAsString + ";path=/";
496        $("#cookie-bar").remove();
497    });
498
499    $(document).on('click', ".faq-accordion-header", function (e) {
500        e.preventDefault();
501        const $this = $(this);
502
503        if ($this.hasClass("collapsed")) {
504            $this.removeClass("collapsed");
505            $this.next().addClass("open");
506        } else {
507            $this.addClass("collapsed");
508            $this.next().removeClass("open");
509        }
510    });
511
512    $(".station-show-more").on("click", function (e) {
513        e.preventDefault();
514        e.stopPropagation();
515        var $this = $(this);
516        var $that = $this.prev();
517
518        if ($that.hasClass("open")) {
519            $that.removeClass("open");
520            $this.removeClass("open");
521            $this.text($this.data("open"));
522        } else {
523            $that.addClass("open");
524            $this.addClass("open");
525            $this.text($this.data("close"));
526        }
527    });
528
529    $(".station-row-county-item").on("click", function (e) {
530        e.preventDefault();
531        var $this = $(this);
532        var $target = $("#" + $this.data("target"));
533
534        if ($(window).outerWidth() < 1024) {
535            $target = $("#m_" + $this.data("target"));
536            $(".station-row-county-item-mobile").removeClass("open");
537        } else {
538            $(".station-row-station-list-wrapper").removeClass("open");
539        }
540
541        if (!$this.hasClass("open")) {
542            $(".footer").find(".station-row-county-item").removeClass("open");
543            $(".footer").find(".station-row-station-list-wrapper").removeClass("open");
544            $(".footer").find(".station-caret").addClass("collapsed");
545            $this.addClass("open");
546            $this.find(".station-caret").removeClass("collapsed");
547            $target.addClass("open");
548
549            $("html, body").animate({
550                scrollTop: $this.offset().top
551            }, 600);
552
553        } else {
554            $this.removeClass("open");
555            $this.find(".station-caret").addClass("collapsed");
556            $target.removeClass("open");
557        }
558    });
559
560    if ($('#stationinputsearchpage').length > 0) {
561
562        var $stationSearch = $('#stationinputsearchpage');
563        /*  if (navigator.geolocation) {
564              navigator.geolocation.getCurrentPosition(showPosition);
565          }*/
566
567        $("#stationsearchpage").on("click", function (e) {
568            e.preventDefault();
569            if ($stationSearch.val().length > 1) {
570                $("#stationsearchform").submit();
571            }
572        });
573
574        $stationSearch.keyup(function (e) {
575            e.preventDefault();
576            if (e.which === 13) {
577                if ($stationSearch.val().length > 1) {
578                    $("#stationsearchform").submit();
579                }
580            }
581
582            $('.station-search__result').css("width", $stationSearch.outerWidth());
583            $("html, body").animate({
584                scrollTop: ($stationSearch.offset().top - 80)
585            }, 600);
586            var temp = searchStation($stationSearch.val());
587            $('.station-search__result').html('');
588            var showMore = temp.length > 6;
589            var loopMax = 6;
590            if (temp.length < loopMax) {
591                loopMax = temp.length;
592            }
593            for (var i = 0; i < loopMax; i++) {
594                $('.station-search__result').append('<li><a href="' + temp[i].url + '"><div class="station-search__result-name text-lg">' + temp[i].title + '</div><div class="station-search__result-status' + '"></div></a></li>');
595            }
596            if (showMore) {
597                $('.station-search__result').append('<li><a href="?sq=' + $stationSearch.val() + '"><div class="station-search__result-showall text-lg">VISA ALLA</div></a></li>');
598
599            }
600            if ($('.station-search__result').html() === '') {
601                $('.station-search__result').append('<li class="text-lg><div class="station-search__notfound text-lg"><div>Tyv&auml;rr hittar vi ingen station som inneh&aring;ller <strong>"' + $('<div/>').text($stationSearch.val()).html() + '"</strong></div>Kontrollera stavningen eller anv&auml;nd kartan f&ouml;r att hitta din n&auml;rmsta Besikta-station.</div></li>');
602            }
603
604        });
605
606        $(".maps-use-geo").on("click", function (e) {
607            e.preventDefault();
608
609            if (navigator.geolocation) {
610                navigator.geolocation.getCurrentPosition(showPosition);
611            } else {
612                $('.station-search__result').append('<li><div class="station-search__notfound"><div>Tyv&auml;rr st&ouml;djer inte din webbl&auml;sare geolocation</div></li>');
613            }
614        });
615
616        function showPosition(position) {
617            BesiktaMapHelper.updateListWithGeoInfo(position);
618        }
619
620        $('.station-input').blur(function () {
621
622            setTimeout(function () {
623
624                if ($('.station-search__result').html().indexOf('ajax-loader.gif') <= 0) {
625                    $('.station-search__result').html('');
626                }
627
628            }, 300);
629        });
630    }
631
632    $("#bookingstartbutton").on("click", function (e) {
633        e.preventDefault();
634        e.stopPropagation();
635        if (isValidRegistrationNumber($("#reg").val())) {
636            $("#startbookingform").submit();
637        } else {
638            $("#errorwrapper").html("<div class=\"booking-alert\">Du har angivet ett felaktigt registreringsnummer</div>");
639        }
640    });
641
642
643    $(".block-station-services-item-header").on("click", function (e) {
644        var $this = $(this);
645        e.preventDefault();
646        e.stopPropagation();
647        if ($this.hasClass("collapsed")) {
648            $this.removeClass("collapsed");
649            $this.next().removeClass("collapsed");
650
651        } else {
652            $this.addClass("collapsed");
653            $this.next().addClass("collapsed");
654
655        }
656    });
657
658    calculateBookingButtonWidth();
659
660    if (location.hash.length > 0) {
661        var loc = $(location.hash);
662        if (loc.length !== 0) {
663            $('html, body').animate({
664                'scrollTop': $(location.hash).offset().top - 100
665            },
666                200);
667        }
668    }
669});
670
671function stopSpacesInRegNr(keypress) {
672    if (keypress.which === 32) {
673        return false;
674    }
675}
676
677var BesiktaMapHelper = {
678    updateListWithGeoInfo: function (position) {
679        var temp = getNearestStation(position.coords.latitude, position.coords.longitude);
680
681        $('.station-search__result').css("width", $('.station-input').outerWidth());
682        $("html, body").animate({
683            scrollTop: ($('.station-input').offset().top - 80)
684        }, 600);
685
686        $('.station-search__result').html('');
687        for (var i = 0; i < temp.length; i++) {
688            $('.station-search__result').append('<li><a href="' + temp[i].url + '"><div class="station-search__result-name">' + temp[i].title + '</div><div class="station-search__result-status open-' + temp[i].dropin + '"></div></a></li>');
689        }
690        $(".maps-use-geo").addClass("active");
691        $('.station-input').focus();
692    },
693    getDistanceFromLatLonInKm: function (lat1, lon1, lat2, lon2) {
694        var R = 6371; // Radius of the earth in km
695        var dLat = this.deg2rad(lat2 - lat1);  // deg2rad below
696        var dLon = this.deg2rad(lon2 - lon1);
697        var a =
698            Math.sin(dLat / 2) * Math.sin(dLat / 2) +
699            Math.cos(this.deg2rad(lat1)) * Math.cos(this.deg2rad(lat2)) *
700            Math.sin(dLon / 2) * Math.sin(dLon / 2)
701            ;
702        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
703        var d = R * c; // Distance in km
704        return d;
705    },
706    deg2rad: function (deg) {
707        return deg * (Math.PI / 180);
708    }
709}
710
711function calculateBookingButtonWidth() {
712    const headerWrapper = $('#header > .main-wrapper');
713    const leftHeader = $('.header-left');
714    const bookingButton = $('#bookmainbutton');
715    const rightSpace = headerWrapper.width() - leftHeader.width();
716    let newPadding = '';
717
718    if (rightSpace < 170) {
719        bookingButton.html('Boka besiktning');
720        const buttonWidth = bookingButton.outerWidth();
721
722        if (buttonWidth > rightSpace) {
723            const paddingToRemove = Math.ceil((buttonWidth - rightSpace) / 2);
724            const sidePadding = parseInt(bookingButton.css('padding-left'));
725            newPadding = sidePadding - paddingToRemove;
726        }
727    } else {
728        const btnImageHtml =$('#bookmainbutton > img')[0];
729
730        if (btnImageHtml !== undefined) {
731            bookingButton.html('Boka besiktning');
732        }
733    }
734    bookingButton.css('padding-inline', newPadding);
735}
736
737$(window).bind('load resize orientationchange', function () {
738    stickyHeader();
739    calculateBookingButtonWidth();
740
741    if ($(window).outerWidth() > 1024) {
742        $('#main').show();
743        $('body').removeClass('menu-open');
744        $('#show-device-menu').removeClass('open');
745        $('.device-header-menu').removeClass('open');
746    }
747});
748
749
750$(document).on('click', '.footer-station-toggler-wrapper .footer-station-toggler', {}, function (e) {
751    e.preventDefault();
752    var $this = $(this);
753    var stations = $(".footer-station-toggler-wrapper").find(".footer-station-toggler");
754    $(".footer-station-toggler-wrapper").find(".station-row-result").removeClass("active");
755    var $that = $("#stat_" + $this.data("stationid"));
756    $that.insertAfter($(stations[stations.length]));
757    if ($(window).outerWidth() < 1024) {
758        $that.insertAfter($(stations[$this.data("stationindex")]));
759    } else if ($(window).outerWidth() < 1200 && $(window).outerWidth() >= 1024) {
760        var ind = ($this.data("stationindex") + 1);
761        if (ind !== stations.length) {
762            if ((ind % 2 === 0) === false) {
763                for (var i = 0; i <= 1; i++) {
764                    ind = (($this.data("stationindex") + 1) + i);
765                    if ((ind % 2 === 0) === true) {
766                        break;
767                    }
768                }
769            }
770        }
771        $that.insertAfter($(stations[ind - 1]));
772
773    } else {
774        var ind = ($this.data("stationindex") + 1);
775        if (ind !== stations.length) {
776            if ((ind % 4 === 0) === false) {
777                for (var i = 0; i <= 3; i++) {
778                    ind = (($this.data("stationindex") + 1) + i);
779                    if ((ind % 4 === 0) === true) {
780                        break;
781                    }
782                }
783            }
784        }
785        $that.insertAfter($(stations[ind - 1]));
786    }
787
788    if ($this.hasClass("open")) {
789        $this.removeClass("open");
790        $this.find(".station-caret").addClass("collapsed");
791        $that.html('');
792        $that.removeClass("active");
793    } else {
794        $this.parent().find(".open").removeClass("open");
795        $this.parent().find(".station-caret").addClass("collapsed");
796        $this.addClass("open");
797        $this.find(".station-caret").removeClass("collapsed");
798
799        $that.addClass("active");
800    }
801});
802
803function stickyHeader() {
804    const currentScrollPos = window.pageYOffset;
805    if ($scrolling === false) {
806        if ($(window).outerWidth() > 768) {
807            const $header = $("#header");
808            if ($header !== null) {
809                if (window.pageYOffset > 175) {
810                    if (prevScrollpos >= currentScrollPos) {
811                        $header.removeClass("hide-header");
812                        if (window.pageYOffset > 175) {
813                            $header.addClass("scroll-header");
814                        } else {
815                            $header.removeClass("scroll-header");
816                        }
817                    } else {
818                        $header.addClass("hide-header");
819                    }
820                } else {
821                    $header.removeClass("hide-header");
822                    $header.removeClass("scroll-header");
823                }
824            }
825        } else {
826            const $deviceheader = $(".device-header");
827            if ($deviceheader !== null) {
828                if (window.pageYOffset > 70) {
829                    if (prevScrollpos >= currentScrollPos) {
830                        $deviceheader.removeClass("hide-header");
831                        if (window.pageYOffset > 70) {
832                            $deviceheader.addClass("scroll-header");
833                        } else {
834                            $deviceheader.removeClass("scroll-header");
835                        }
836                    } else {
837                        $deviceheader.addClass("hide-header");
838                    }
839                } else {
840                    $deviceheader.removeClass("hide-header");
841                    $deviceheader.removeClass("scroll-header");
842                }
843            }
844        }
845    }
846    prevScrollpos = currentScrollPos;
847}
848
849function isValidEmailAddress(emailAddress) {
850    var pattern = /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i;
851    return pattern.test(emailAddress);
852};
853
854function isValidRegistrationNumber(reg) {
855    var pattern = /[A-Za-z]{3}[0-9]{2}[A-Za-z0-9]{1}/g;
856    return pattern.test(reg);
857};
858
859function isValidMobile(mobile) {
860    mobile = mobile.replace(/ /g, '');
861    mobile = mobile.replace(/-/g, '');
862    var pattern = /^([+]46)\s*(7[02369])\s*(\d{4})\s*(\d{3})$/i;
863    if (pattern.test(mobile)) {
864        return true;
865    }
866    pattern = /^s*(07[02369])\s*(\d{4})\s*(\d{3})$/i;
867    if (pattern.test(mobile)) {
868        return true;
869    }
870    pattern = /^s*(0[{1-9}])\s*(\d{5,10})$/i;
871    if (pattern.test(mobile)) {
872        return true;
873    }
874    pattern = /^([+]46)\s*(\d{7,10})$/i;
875    return pattern.test(mobile);
876};
877
878function strip(html) {
879    var tmp = document.createElement("DIV");
880    tmp.innerHTML = html;
881    return tmp.textContent || tmp.innerText || "";
882}
883
884if (!String.prototype.includes) {
885    String.prototype.includes = function (search, start) {
886        'use strict';
887
888        if (search instanceof RegExp) {
889            throw TypeError('first argument must not be a RegExp');
890        }
891        if (start === undefined) { start = 0; }
892        return this.indexOf(search, start) !== -1;
893    };
894}
895
896function loadPartialPage(path) {
897    fetch(path)
898        .then((response) => response.text())
899        .then((html) => {
900            $("#partialload").html(html);
901        })
902        .catch((error) => {
903        });
904}
905
906function handleDifferentBrowsers() {
907    // Conditional IE10 and IE11 handling.
908    var UAString = navigator.userAgent;
909    var isSafari = /^((?!chrome|android).)*safari/i.test(UAString);
910
911    if (UAString.indexOf('MSIE 10') !== -1) {
912        document.documentElement.setAttribute('data-ie', 'MSIE10');
913    }
914
915    if (UAString.indexOf('Trident') !== -1 && UAString.indexOf('rv:11') !== -1) {
916        document.documentElement.setAttribute('data-ie', 'MSIE11');
917    }
918
919    if (isSafari) {
920        document.documentElement.setAttribute('data-ie', 'Safari');
921    }
922
923    if(document.documentElement.getAttribute('data-ie')){
924        $('[data-ieimg]').each(function () {
925            const $this = $(this);
926            $this.attr('style','background-image:url(' + $this.data('ieimg') + ');');
927        });
928    }
929}
930
931//add rel attributes to all links that open a new tab
932window.addEventListener("load", () =>
933    [...document.querySelectorAll("a[target=_blank]")]
934        .forEach(lnk => lnk.setAttribute("rel", "noopener noreferrer"))
935);
936
937/* Start booking block start */
938$(document).on('click', '#startblockbookingbutton', {}, function (e) {
939    e.preventDefault();
940    e.stopPropagation();
941    var reg = $("#reg").val();
942    var bsi = $("#bsi").val();
943    var camp = $("#campaign").val();
944    if (isValidRegistrationNumber(reg)) {
945        var postData = {};
946        postData["reg"] = reg;
947        postData["bsi"] = bsi;
948        postData["camp"] = camp;
949
950        $.ajax({
951            contentType: "application/json; charset=utf-8",
952            data: JSON.stringify(postData),
953            dataType: "json",
954            url: "/Service/ValidateBookingStart",
955            type: "post",
956            cache: false,
957            success: function (data) {
958                if (data.success) {
959                    location.href = data.url + "?bsi=" + bsi + "&reg=" + reg + "&campaign=" + camp;
960                } else {
961                    $("#errorwrapper").html("<div class=\"booking-alert\">NÃ¥got gick fel</div>");
962                }
963            },
964            error: function () {
965                $("#errorwrapper").html("<div class=\"booking-alert\">NÃ¥got gick fel</div>");
966            }
967        });
968    } else {
969        $("#errorwrapper").html("<div class=\"booking-alert\">Du har angivet ett felaktigt registreringsnummer</div>");
970    }
971});
972
973$(document).on('keydown', '#reg', {}, function (e) {
974    if (e.keyCode === 13) {
975        $('#startblockbookingbutton').click();
976    }
977});
978/* Start booking block stop */
979
980/* This view acts as a rendering template to render InitScript(and server-side Form's descriptor) in FormContainerBlock's client-side for Form[75a6fb6d-5908-4afa-9caf-99d6a4489d26].
981TECHNOTE: all serverside (paths, dynamic values) of EPiServerForms will be transfered to client side here in this section. */
982(function initializeOnRenderingFormDescriptor() {
983    if (typeof epi === 'undefined') { return; }
984    // each workingFormInfo is store inside epi.EPiServer.Forms, lookup by its FormGuid
985    var workingFormInfo = epi.EPiServer.Forms["75a6fb6d-5908-4afa-9caf-99d6a4489d26"] = {
986        Id: "75a6fb6d-5908-4afa-9caf-99d6a4489d26",
987        Name: "Registreringsbesiktning - Bokning",
988        // whether this Form can be submitted which relates to the visitor's data (cookie, identity) and Form's settings (AllowAnonymous, AllowXXX)
989
990        SubmittableStatus: { "submittable": true, "message": "" },
991        ConfirmMessage: "Tack! Vi kommer att svara dig inom kort.",
992        ShowNavigationBar: false,
993        ShowSummarizedData: false,
994
995        // serialize the dependency configuration of this form to clientside
996        DependenciesInfo: [],
997        // keep all fieldName which are not satisfied the field dependency conditions
998        DependencyInactiveElements: [],
999
1000        // Validation info, for executing validating on client side
1001        ValidationInfo: [{ "targetElementName": "__field_1418", "targetElementId": "d7dc1a5d-ebc4-4a7f-bfd4-2ae24943c950", "validators": [{ "type": "EPiServer.Forms.Implementation.Validation.RequiredValidator", "description": null, "model": { "message": "Fältet är obligatoriskt.", "validationCssClass": "ValidationRequired", "additionalAttributes": { "required": "", "aria-required": "true" } } }] }, { "targetElementName": "__field_1416", "targetElementId": "bf5b4e06-d13d-46ca-93f2-75b290b95bea", "validators": [{ "type": "EPiServer.Forms.Implementation.Validation.RequiredValidator", "description": null, "model": { "message": "Fältet är obligatoriskt.", "validationCssClass": "ValidationRequired", "additionalAttributes": { "required": "", "aria-required": "true" } } }
1001, { "type": "EPiServer.Forms.Implementation.Validation.EmailValidator", "description": null, "model": { "jsPattern": "(^$)|(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)", "dotNetPattern": "(^$)|(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)", "message": "Ange en giltig e-postadress.", "validationCssClass": null, "additionalAttributes": null } }] }, { "targetElementName": "__field_1417", "targetElementId": "f0c7d112-a0e4-4f6d-a76c-48be9ed423d4", "validators": [{ "type": "EPiServer.Forms.Implementation.Validation.RequiredValidator", "description": null, "model": { "message": "Fältet är obligatoriskt.", "validationCssClass": "ValidationRequired", "additionalAttributes": { "required": "", "aria-required": "true" } } }] }, { "targetElementName": "__field_1415", "targetElementId": "dcf6f1ca-4589-466e-88b3-1558fa200857", "validators": [{ "type": "EPiServer.Forms.Implementation.Validation.RequiredValidator", "description": null, "model": { "message": "Fältet är obligatoriskt.", "validationCssClass": "ValidationRequired", "additionalAttributes": { "required": "", "aria-required": "true" } } }] }],
1002        // Steps information for driving multiple-step Forms.
1003        StepsInfo: {
1004            Steps: [{ "index": 0, "attachedUrl": "", "dependField": null, "dependCondition": null, "isActive": true, "attachedContentLink": "", "dependValue": "", "elementName": "__field_", "guid": "00000000-0000-0000-0000-000000000000" }]
1005        },
1006        FieldsExcludedInSubmissionSummary: [],
1007        ElementsInfo: { "__field_1418": { "type": "EPiServer.Forms.Implementation.Elements.TextboxElementBlock", "friendlyName": "Namn", "customBinding": false }, "__field_1420": { "type": "EPiServer.Forms.Implementation.Elements.TextboxElementBlock", "friendlyName": "Telefonnummer", "customBinding": false }, "__field_1416": { "type": "EPiServer.Forms.Implementation.Elements.TextboxElementBlock", "friendlyName": "E-post", "customBinding": false }, "__field_1417": { "type": "EPiServer.Forms.Implementation.Elements.TextboxElementBlock", "friendlyName": "Stad", "customBinding": false }, "__field_1415": { "type": "EPiServer.Forms.Implementation.Elements.TextboxElementBlock", "friendlyName": "Regnr eller ärendenr", "customBinding": false }, "__field_1421": { "type": "EPiServer.Forms.Implementation.Elements.TextareaElementBlock", "friendlyName": "Beskrivning av ärende", "customBinding": false }, "__field_1419": { "type": "EPiServer.Forms.Implementation.Elements.SubmitButtonElementBlock", "friendlyName": "Skickaknapp", "customBinding": false } },
1008        DataSubmitController: "/EPiServer.Forms/DataSubmit"
1009
1010    };
1011
1012    /// TECHNOTE: Calculation at FormInfo level, and these values will be static input for later processing.
1013    workingFormInfo.StepsInfo.FormHasNoStep_VirtualStepCreated = true;  // this FLAG will be true, if Editor does not put any FormStep. Engine will create a virtual step, with empty GUID
1014    workingFormInfo.StepsInfo.FormHasNothing = false;  // this FLAG will be true if FormContainer has no element at all
1015    workingFormInfo.StepsInfo.AllStepsAreNotLinked = true;  // this FLAG will be true, if all steps all have contentLink=="" (emptyString)
1016})();

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.