From 5eeb2bbeb8c71ae813808ee0e8d09293c4abe1c1 Mon Sep 17 00:00:00 2001 From: Ignat Beresnev Date: Thu, 19 Jan 2023 04:10:57 +0100 Subject: Revise README documentation for examples and plugins (#2736) --- .../0.9/scripts/platform-content-handler.js | 359 +++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 examples/gradle/dokka-versioning-multimodule-example/previousDocVersions/0.9/scripts/platform-content-handler.js (limited to 'examples/gradle/dokka-versioning-multimodule-example/previousDocVersions/0.9/scripts/platform-content-handler.js') diff --git a/examples/gradle/dokka-versioning-multimodule-example/previousDocVersions/0.9/scripts/platform-content-handler.js b/examples/gradle/dokka-versioning-multimodule-example/previousDocVersions/0.9/scripts/platform-content-handler.js new file mode 100644 index 00000000..def9dae8 --- /dev/null +++ b/examples/gradle/dokka-versioning-multimodule-example/previousDocVersions/0.9/scripts/platform-content-handler.js @@ -0,0 +1,359 @@ +filteringContext = { + dependencies: {}, + restrictedDependencies: [], + activeFilters: [] +} +let highlightedAnchor; +let topNavbarOffset; +let instances = []; +let sourcesetNotification; + +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 osDarkSchemePreferred = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches + const darkModeEnabled = storage ? JSON.parse(storage) : osDarkSchemePreferred + const element = document.getElementById("theme-toggle-button") + initPlayground(darkModeEnabled ? 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) + filteringContext.activeFilters = filteringContext.restrictedDependencies + .filter(q => parsed.indexOf(q) == -1) + } else { + filteringContext.activeFilters = filteringContext.restrictedDependencies + } + refreshFiltering() +} + +function filterSourceset(sourceset) { + filteringContext.activeFilters = filteringContext.activeFilters.filter(p => p != sourceset) + refreshFiltering() + addSourcesetFilterToCache(sourceset) +} + +function unfilterSourceset(sourceset) { + if (filteringContext.activeFilters.length == 0) { + filteringContext.activeFilters = filteringContext.dependencies[sourceset].concat([sourceset]) + refreshFiltering() + filteringContext.dependencies[sourceset].concat([sourceset]).forEach(p => removeSourcesetFilterFromCache(p)) + } else { + filteringContext.activeFilters.push(sourceset) + refreshFiltering() + removeSourcesetFilterFromCache(sourceset) + } + +} + +function addSourcesetFilterToCache(sourceset) { + let cached = localStorage.getItem('inactive-filters') + if (cached) { + let parsed = JSON.parse(cached) + localStorage.setItem('inactive-filters', JSON.stringify(parsed.concat([sourceset]))) + } else { + localStorage.setItem('inactive-filters', JSON.stringify([sourceset])) + } +} + +function removeSourcesetFilterFromCache(sourceset) { + let cached = localStorage.getItem('inactive-filters') + if (cached) { + let parsed = JSON.parse(cached) + localStorage.setItem('inactive-filters', JSON.stringify(parsed.filter(p => p != sourceset))) + } +} + +function toggleSections(target) { + localStorage.setItem('active-tab', JSON.stringify(target.getAttribute("data-togglable"))) + const activateTabs = (containerClass) => { + for (const element of document.getElementsByClassName(containerClass)) { + for (const child of element.children) { + if (child.getAttribute("data-togglable") === target.getAttribute("data-togglable")) { + child.setAttribute("data-active", "") + } else { + child.removeAttribute("data-active") + } + } + } + } + + activateTabs("tabs-section") + activateTabs("tabs-section-body") +} + +function toggleSectionsEventHandler(evt) { + if (!evt.target.getAttribute("data-togglable")) return + toggleSections(evt.target) +} + +function togglePlatformDependent(e, container) { + let target = e.target + if (target.tagName != 'BUTTON') return; + let index = target.getAttribute('data-toggle') + + for (let child of container.children) { + if (child.hasAttribute('data-toggle-list')) { + for (let bm of child.children) { + if (bm == target) { + bm.setAttribute('data-active', "") + } else if (bm != target) { + bm.removeAttribute('data-active') + } + } + } else if (child.getAttribute('data-togglable') == index) { + child.setAttribute('data-active', "") + } else { + child.removeAttribute('data-active') + } + } +} + +function refreshFiltering() { + let sourcesetList = filteringContext.activeFilters + document.querySelectorAll("[data-filterable-set]") + .forEach( + elem => { + let platformList = elem.getAttribute("data-filterable-set").split(' ').filter(v => -1 !== sourcesetList.indexOf(v)) + elem.setAttribute("data-filterable-current", platformList.join(' ')) + } + ) + refreshFilterButtons() + refreshPlatformTabs() + refreshNoContentNotification() +} + +function refreshNoContentNotification() { + const element = document.getElementsByClassName("main-content")[0] + if(filteringContext.activeFilters.length === 0){ + element.style.display = "none"; + + const appended = document.createElement("div") + appended.className = "filtered-message" + appended.innerText = "All documentation is filtered, please adjust your source set filters in top-right corner of the screen" + sourcesetNotification = appended + element.parentNode.prepend(appended) + } else { + if(sourcesetNotification) sourcesetNotification.remove() + element.style.display = "block" + } +} + +function refreshPlatformTabs() { + document.querySelectorAll(".platform-hinted > .platform-bookmarks-row").forEach( + p => { + let active = false; + let firstAvailable = null + p.childNodes.forEach( + element => { + if (element.getAttribute("data-filterable-current") != '') { + if (firstAvailable == null) { + firstAvailable = element + } + if (element.hasAttribute("data-active")) { + active = true; + } + } + } + ) + if (active == false && firstAvailable) { + firstAvailable.click() + } + } + ) +} + +function refreshFilterButtons() { + document.querySelectorAll("#filter-section > button") + .forEach(f => { + if (filteringContext.activeFilters.indexOf(f.getAttribute("data-filter")) != -1) { + f.setAttribute("data-active", "") + } else { + f.removeAttribute("data-active") + } + }) +} -- cgit