<commit_before>filteringContext = {
    dependencies: {},
    restrictedDependencies: [],
    activeFilters: []
}
let highlightedAnchor;
let topNavbarOffset;
let instances = [];

const samplesDarkThemeName = 'darcula'
const samplesLightThemeName = 'idea'

window.addEventListener('load', () => {
    document.querySelectorAll("div[data-platform-hinted]")
        .forEach(elem => elem.addEventListener('click', (event) => togglePlatformDependent(event, elem)))
    document.querySelectorAll("div[tabs-section]")
        .forEach(elem => elem.addEventListener('click', (event) => toggleSectionsEventHandler(event)))
    const filterSection = document.getElementById('filter-section')
    if (filterSection) {
        filterSection.addEventListener('click', (event) => filterButtonHandler(event))
        initializeFiltering()
    }
    initTabs()
    handleAnchor()
    initHidingLeftNavigation()
    topNavbarOffset = document.getElementById('navigation-wrapper')
    darkModeSwitch()
})

const darkModeSwitch = () => {
    const localStorageKey = "dokka-dark-mode"
    const storage = localStorage.getItem(localStorageKey)
    const savedDarkMode = storage ? JSON.parse(storage) : false
    const element = document.getElementById("theme-toggle-button")
    initPlayground(savedDarkMode ? samplesDarkThemeName : samplesLightThemeName)

    element.addEventListener('click', () => {
        const enabledClasses = document.getElementsByTagName("html")[0].classList
        enabledClasses.toggle("theme-dark")

        //if previously we had saved dark theme then we set it to light as this is what we save in local storage
        const darkModeEnabled = enabledClasses.contains("theme-dark")
        if (darkModeEnabled) {
            initPlayground(samplesDarkThemeName)
        }
        else {
            initPlayground(samplesLightThemeName)
        }
        localStorage.setItem(localStorageKey, JSON.stringify(darkModeEnabled))
    })
}

const initPlayground = (theme) => {
    if(!samplesAreEnabled()) return
    instances.forEach(instance => instance.destroy())
    instances = []

    // Manually tag code fragments as not processed by playground since we also manually destroy all of its instances
    document.querySelectorAll('code.runnablesample').forEach(node => {
        node.removeAttribute("data-kotlin-playground-initialized");
    })

    KotlinPlayground('code.runnablesample', {
        getInstance: playgroundInstance => {
            instances.push(playgroundInstance)
        },
        theme: theme
    });
}

// We check if type is accessible from the current scope to determine if samples script is present
// As an alternative we could extract this samples-specific script to new js file but then we would handle dark mode in 2 separate files which is not ideal
const samplesAreEnabled = () => {
    try {
        KotlinPlayground
        return true
    } catch (e) {
        return false
    }
}


const initHidingLeftNavigation = () => {
    document.getElementById("leftToggler").onclick = function (event) {
        //Events need to be prevented from bubbling since they will trigger next handler
        event.preventDefault();
        event.stopPropagation();
        event.stopImmediatePropagation();
        document.getElementById("leftColumn").classList.toggle("open");
    }

    document.getElementById("main").onclick = () => {
        document.getElementById("leftColumn").classList.remove("open");
    }
}

// Hash change is needed in order to allow for linking inside the same page with anchors
// If this is not present user is forced to refresh the site in order to use an anchor
window.onhashchange = handleAnchor

function scrollToElementInContent(element) {
    const scrollToElement = () => document.getElementById('main').scrollTo({
        top: element.offsetTop - topNavbarOffset.offsetHeight,
        behavior: "smooth"
    })

    const waitAndScroll = () => {
        setTimeout(() => {
            if (topNavbarOffset) {
                scrollToElement()
            } else {
                waitForScroll()
            }
        }, 50)
    }

    if (topNavbarOffset) {
        scrollToElement()
    } else {
        waitAndScroll()
    }
}


function handleAnchor() {
    if (highlightedAnchor) {
        highlightedAnchor.classList.remove('anchor-highlight')
        highlightedAnchor = null;
    }

    let searchForTab = function (element) {
        if (element && element.hasAttribute) {
            if (element.hasAttribute("data-togglable")) return element;
            else return searchForTab(element.parentNode)
        } else return null
    }
    let anchor = window.location.hash
    if (anchor != "") {
        anchor = anchor.substring(1)
        let element = document.querySelector('a[data-name="' + anchor + '"]')
        if (element) {
            let tab = searchForTab(element)
            if (tab) {
                toggleSections(tab)
            }
            const content = element.nextElementSibling
            if (content) {
                content.classList.add('anchor-highlight')
                highlightedAnchor = content
            }

            scrollToElementInContent(element)
        }
    }
}

function initTabs() {
    document.querySelectorAll("div[tabs-section]")
        .forEach(element => {
            showCorrespondingTabBody(element)
            element.addEventListener('click', (event) => toggleSectionsEventHandler(event))
        })
    let cached = localStorage.getItem("active-tab")
    if (cached) {
        let parsed = JSON.parse(cached)
        let tab = document.querySelector('div[tabs-section] > button[data-togglable="' + parsed + '"]')
        if (tab) {
            toggleSections(tab)
        }
    }
}

function showCorrespondingTabBody(element) {
    const key = element.querySelector("button[data-active]").getAttribute("data-togglable")
    document.querySelector(".tabs-section-body")
        .querySelector("div[data-togglable='" + key + "']")
        .setAttribute("data-active", "")
}

function filterButtonHandler(event) {
    if (event.target.tagName == "BUTTON" && event.target.hasAttribute("data-filter")) {
        let sourceset = event.target.getAttribute("data-filter")
        if (filteringContext.activeFilters.indexOf(sourceset) != -1) {
            filterSourceset(sourceset)
        } else {
            unfilterSourceset(sourceset)
        }
    }
}

function initializeFiltering() {
    filteringContext.dependencies = JSON.parse(sourceset_dependencies)
    document.querySelectorAll("#filter-section > button")
        .forEach(p => filteringContext.restrictedDependencies.push(p.getAttribute("data-filter")))
    Object.keys(filteringContext.dependencies).forEach(p => {
        filteringContext.dependencies[p] = filteringContext.dependencies[p]
            .filter(q => -1 !== filteringContext.restrictedDependencies.indexOf(q))
    })
    let cached = window.localStorage.getItem('inactive-filters')
    if (cached) {
        let parsed = JSON.parse(cached)<commit_msg>Fix js error on pages without tabs (#2127)<commit_after>filteringContext = {
    dependencies: {},
    restrictedDependencies: [],
    activeFilters: []
}
let highlightedAnchor;
let topNavbarOffset;
let instances = [];

const samplesDarkThemeName = 'darcula'
const samplesLightThemeName = 'idea'

window.addEventListener('load', () => {
    document.querySelectorAll("div[data-platform-hinted]")
        .forEach(elem => elem.addEventListener('click', (event) => togglePlatformDependent(event, elem)))
    document.querySelectorAll("div[tabs-section]")
        .forEach(elem => elem.addEventListener('click', (event) => toggleSectionsEventHandler(event)))
    const filterSection = document.getElementById('filter-section')
    if (filterSection) {
        filterSection.addEventListener('click', (event) => filterButtonHandler(event))
        initializeFiltering()
    }
    initTabs()
    handleAnchor()
    initHidingLeftNavigation()
    topNavbarOffset = document.getElementById('navigation-wrapper')
    darkModeSwitch()
})

const darkModeSwitch = () => {
    const localStorageKey = "dokka-dark-mode"
    const storage = localStorage.getItem(localStorageKey)
    const savedDarkMode = storage ? JSON.parse(storage) : false
    const element = document.getElementById("theme-toggle-button")
    initPlayground(savedDarkMode ? samplesDarkThemeName : samplesLightThemeName)

    element.addEventListener('click', () => {
        const enabledClasses = document.getElementsByTagName("html")[0].classList
        enabledClasses.toggle("theme-dark")

        //if previously we had saved dark theme then we set it to light as this is what we save in local storage
        const darkModeEnabled = enabledClasses.contains("theme-dark")
        if (darkModeEnabled) {
            initPlayground(samplesDarkThemeName)
        } else {
            initPlayground(samplesLightThemeName)
        }
        localStorage.setItem(localStorageKey, JSON.stringify(darkModeEnabled))
    })
}

const initPlayground = (theme) => {
    if (!samplesAreEnabled()) return
    instances.forEach(instance => instance.destroy())
    instances = []

    // Manually tag code fragments as not processed by playground since we also manually destroy all of its instances
    document.querySelectorAll('code.runnablesample').forEach(node => {
        node.removeAttribute("data-kotlin-playground-initialized");
    })

    KotlinPlayground('code.runnablesample', {
        getInstance: playgroundInstance => {
            instances.push(playgroundInstance)
        },
        theme: theme
    });
}

// We check if type is accessible from the current scope to determine if samples script is present
// As an alternative we could extract this samples-specific script to new js file but then we would handle dark mode in 2 separate files which is not ideal
const samplesAreEnabled = () => {
    try {
        KotlinPlayground
        return true
    } catch (e) {
        return false
    }
}


const initHidingLeftNavigation = () => {
    document.getElementById("leftToggler").onclick = function (event) {
        //Events need to be prevented from bubbling since they will trigger next handler
        event.preventDefault();
        event.stopPropagation();
        event.stopImmediatePropagation();
        document.getElementById("leftColumn").classList.toggle("open");
    }

    document.getElementById("main").onclick = () => {
        document.getElementById("leftColumn").classList.remove("open");
    }
}

// Hash change is needed in order to allow for linking inside the same page with anchors
// If this is not present user is forced to refresh the site in order to use an anchor
window.onhashchange = handleAnchor

function scrollToElementInContent(element) {
    const scrollToElement = () => document.getElementById('main').scrollTo({
        top: element.offsetTop - topNavbarOffset.offsetHeight,
        behavior: "smooth"
    })

    const waitAndScroll = () => {
        setTimeout(() => {
            if (topNavbarOffset) {
                scrollToElement()
            } else {
                waitForScroll()
            }
        }, 50)
    }

    if (topNavbarOffset) {
        scrollToElement()
    } else {
        waitAndScroll()
    }
}


function handleAnchor() {
    if (highlightedAnchor) {
        highlightedAnchor.classList.remove('anchor-highlight')
        highlightedAnchor = null;
    }

    let searchForTab = function (element) {
        if (element && element.hasAttribute) {
            if (element.hasAttribute("data-togglable")) return element;
            else return searchForTab(element.parentNode)
        } else return null
    }
    let anchor = window.location.hash
    if (anchor != "") {
        anchor = anchor.substring(1)
        let element = document.querySelector('a[data-name="' + anchor + '"]')
        if (element) {
            let tab = searchForTab(element)
            if (tab) {
                toggleSections(tab)
            }
            const content = element.nextElementSibling
            if (content) {
                content.classList.add('anchor-highlight')
                highlightedAnchor = content
            }

            scrollToElementInContent(element)
        }
    }
}

function initTabs() {
    document.querySelectorAll("div[tabs-section]")
        .forEach(element => {
            showCorrespondingTabBody(element)
            element.addEventListener('click', (event) => toggleSectionsEventHandler(event))
        })
    let cached = localStorage.getItem("active-tab")
    if (cached) {
        let parsed = JSON.parse(cached)
        let tab = document.querySelector('div[tabs-section] > button[data-togglable="' + parsed + '"]')
        if (tab) {
            toggleSections(tab)
        }
    }
}

function showCorrespondingTabBody(element) {
    const buttonWithKey = element.querySelector("button[data-active]")
    if (buttonWithKey) {
        const key = buttonWithKey.getAttribute("data-togglable")
        document.querySelector(".tabs-section-body")
            .querySelector("div[data-togglable='" + key + "']")
            .setAttribute("data-active", "")
    }
}

function filterButtonHandler(event) {
    if (event.target.tagName == "BUTTON" && event.target.hasAttribute("data-filter")) {
        let sourceset = event.target.getAttribute("data-filter")
        if (filteringContext.activeFilters.indexOf(sourceset) != -1) {
            filterSourceset(sourceset)
        } else {
            unfilterSourceset(sourceset)
        }
    }
}

function initializeFiltering() {
    filteringContext.dependencies = JSON.parse(sourceset_dependencies)
    document.querySelectorAll("#filter-section > button")
        .forEach(p => filteringContext.restrictedDependencies.push(p.getAttribute("data-filter")))
    Object.keys(filteringContext.dependencies).forEach(p => {
        filteringContext.dependencies[p] = filteringContext.dependencies[p]
            .filter(q => -1 !== filteringContext.restrictedDependencies.indexOf(q))
    })
    let cached = window.localStorage.getItem('inactive-filters')
    if (cached) {
        let parsed = JSON.parse(cached)
{'fraction_non_alphanumeric': 0.11254677681282214, 'fraction_numerical': 0.0012709171785638637, 'mean_word_length': 2.939916550764951, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4942036', 'n_tokens_mistral': 3702, 'n_tokens_neox': 3683, 'n_words': 800}