/* SmartRoadSense */

function thousands_commas(input, adapt = true) {
    let unit = '';
    let n = input;
    if(input >= 10000000 && adapt) {
        n = input / 1000000.0;
        unit = 'M';
    }
    else if(input >= 10000 && adapt) {
        n = input / 1000.0;
        unit = 'K';
    }

    return (Math.round(n * 100) / 100).toFixed(1) + unit;
}

// Taken from https://stackoverflow.com/a/33928558/3118
function copy_to_clipboard_legacy(text) {
    if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
        var textarea = document.createElement("textarea");
        textarea.textContent = text;
        textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in MS Edge.
        document.body.appendChild(textarea);
        textarea.select();

        try {
            return document.execCommand("copy"); // Security exception may be thrown by some browsers
        }
        catch (ex) {
            console.warn("Copy to clipboard failed.", ex);
            return false;
        }
        finally {
            document.body.removeChild(textarea);
        }
    }
    else {
        return false;
    }
}
async function copy_to_clipboard(text) {
    if (window.clipboardData && window.clipboardData.setData) {
        // IE specific code path
        return clipboardData.setData("Text", text);
    }
    else if(navigator.clipboard) {
        try {
            await navigator.clipboard.writeText(text);
            return true;
        }
        catch(err) {
            console.warn('Failed using navigator.clipboard copy.', err);
            return copy_to_clipboard_legacy(text);
        }
    }
    else {
        return copy_to_clipboard_legacy(text);
    }
}

function update_stats() {
    $.getJSON("/ws/count.php", function(json) {
        var raw = json.count_raw;
        var aggregated = json.count_aggregate;

        var kilometres = aggregated * 20 / 1000.0;
        var axis_data = raw * 300;

        $('.data-accel-values').text(thousands_commas(axis_data));
        $('.data-points').text(thousands_commas(raw));
        $('.data-roads').text(thousands_commas(kilometres, false));
    });
}

var listOfScrollableElements = [];

function srs_onscroll(eventObject, quick) {
    var scrollTop = $(document).scrollTop();
    if(scrollTop > 10) {
        $('nav.navbar').addClass('scrolled');
    }
    else {
        $('nav.navbar').removeClass('scrolled');
    }

    if(listOfScrollableElements.length > 0) {
        if(listOfScrollableElements[0].yOffset < (scrollTop + ($(window).height() * 0.9))) {
            if(quick) {
                $(listOfScrollableElements[0].element).addClass('no-trans');
            }
            $(listOfScrollableElements[0].element).removeClass('scroll-in');
            listOfScrollableElements.splice(0, 1);
        }
    }
}

$(document).ready(function() {
    // Build scrollable element list
    $('.scroll-in').each(function(index, element) {
        var yPos = $(element).offset().top;

        listOfScrollableElements.push({
            element: element,
            yOffset: yPos
        });
    });
    listOfScrollableElements.sort(function(a, b) { return a.yOffset - b.yOffset; });

    srs_onscroll(null, true);

    // Scroll handling
    $(window).scroll(srs_onscroll);

    // When/if window resizes, execute all animations since positions are not guaranteed anymore
    $(window).resize(function() {
        for(var i = 0; i < listOfScrollableElements.length; ++i) {
            $(listOfScrollableElements[i].element).addClass('no-trans').removeClass('scroll-in');
        }
        listOfScrollableElements = [];
    });

    // Navbar collapse/expand
    $('nav.navbar').on('show.bs.collapse', function () {
        $('nav.navbar').addClass('expanded');
    })
    $('nav.navbar').on('hide.bs.collapse', function () {
        $('nav.navbar').removeClass('expanded');
    })

    // Stats data loading
    if($('.data-accel-values,.data-points,.data-roads').length > 0) {
        update_stats();
        setTimeout(update_stats, 60000);
    }

    // BibTeX loading
    $('.bibliography .bibtex-link a').click(async function(event) {
        var bib = $(this).data('bibtex');
        $('.bibliography .bibtex').fadeIn().find('.output').text(bib);

        if(await copy_to_clipboard(bib))
            $('.bibliography .bibtex .copy-confirmation').show();
        else
            $('.bibliography .bibtex .copy-confirmation').hide();
    });
});

@@ -2173,44 +2173,8 @@
 %0A%7D%0A%0A
-var listOfScrollableElements = %5B%5D;%0A%0A
 func
@@ -2405,390 +2405,340 @@
   %7D%0A
-%0A    if(listOfScrollableElements.length %3E 0) %7B%0A        if(listOfScrollableElements%5B0%5D.yOffset %3C (scrollTop + ($(window).height() * 0.9))) %7B%0A            if(quick) %7B%0A                $(listOfScrollableElements%5B0%5D.element).addClass('no-trans');%0A            %7D%0A            $(listOfScrollableElements%5B0%5D.element).removeClass('scroll-in');%0A            listOfScrollableElements.splice(0, 1);
+%7D%0A%0A$(document).ready(function() %7B%0A    // Scroll observers%0A    const itemScrollObserver = new IntersectionObserver(function(entries, obs) %7B%0A        entries.forEach(entry =%3E %7B%0A            console.log('Observed item ' + entry.target + ', intersection ratio ' + entry.intersectionRatio);%0A            if(entry.intersectionRatio %3E= 0.5) %7B
 %0A   
@@ -2746,95 +2746,45 @@
     
-%7D%0A
     
-%7D%0A%7D%0A%0A$(document).ready(function() %7B%0A    // Build scrollable element list%0A    $
+    $(entry.target).removeClass
 ('
-.
 scro
@@ -2794,729 +2794,255 @@
 in')
-.each(function(index, element) %7B%0A        var yPos = $(element).offset().top;%0A%0A        listOfScrollableElements.push(%7B%0A            element: element,%0A            yOffset: yPos%0A        %7D);%0A    %7D);%0A    listOfScrollableElements.sort(function(a, b) %7B return a.yOffset - b.yOffset;
+;%0A                obs.unobserve(entry.target);%0A            %7D%0A        %7D);%0A    %7D, %7B threshold: 0.5
  %7D);%0A
-%0A
     
-srs_onscroll(null, true);%0A%0A    // Scroll handling%0A    $(window).scroll(srs_onscroll);%0A%0A    // When/if window resizes, execute all animations since positions are not guaranteed anymore%0A    $(window).resize(function() %7B%0A        for(var i = 0; i %3C listOfScrollableElements.length; ++i) %7B%0A            $(listOfScrollableElements%5Bi%5D.element).addClass('no-trans').removeClass('scroll-in');%0A        %7D%0A        listOfScrollableElements = %5B%5D;%0A    %7D
+document.querySelectorAll('.scroll-in').forEach(item =%3E %7B%0A        itemScrollObserver.observe(item);%0A    %7D);%0A%0A    $(window).scroll(srs_onscroll
 );%0A%0A

Use IntersectionObserver for header animations