uni

Thing1's amazing uni repo
Log | Files | Refs | Submodules

script.js (21563B)


      1 /*
      2  * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
      6  */
      7 
      8 var moduleSearchIndex;
      9 var packageSearchIndex;
     10 var typeSearchIndex;
     11 var memberSearchIndex;
     12 var tagSearchIndex;
     13 
     14 var oddRowColor = "odd-row-color";
     15 var evenRowColor = "even-row-color";
     16 var sortAsc = "sort-asc";
     17 var sortDesc = "sort-desc";
     18 var tableTab = "table-tab";
     19 var activeTableTab = "active-table-tab";
     20 
     21 const linkIcon = "Link icon";
     22 const linkToSection = "Link to this section";
     23 
     24 if (typeof hljs !== "undefined") {
     25     try {
     26         hljs.highlightAll();
     27     } catch (err) {
     28         console.error(err)
     29     }
     30 }
     31 
     32 function loadScripts(doc, tag) {
     33     createElem(doc, tag, 'script-files/search.js');
     34 
     35     createElem(doc, tag, 'module-search-index.js');
     36     createElem(doc, tag, 'package-search-index.js');
     37     createElem(doc, tag, 'type-search-index.js');
     38     createElem(doc, tag, 'member-search-index.js');
     39     createElem(doc, tag, 'tag-search-index.js');
     40 }
     41 
     42 function createElem(doc, tag, path) {
     43     var script = doc.createElement(tag);
     44     var scriptElement = doc.getElementsByTagName(tag)[0];
     45     script.src = pathtoroot + path;
     46     scriptElement.parentNode.insertBefore(script, scriptElement);
     47 }
     48 
     49 // Helper for  making content containing release names comparable lexicographically
     50 function makeComparable(s) {
     51     return s.toLowerCase().replace(/(\d+)/g,
     52         function(n, m) {
     53             return ("000" + m).slice(-4);
     54         });
     55 }
     56 
     57 // Switches between two styles depending on a condition
     58 function toggleStyle(classList, condition, trueStyle, falseStyle) {
     59     if (condition) {
     60         classList.remove(falseStyle);
     61         classList.add(trueStyle);
     62     } else {
     63         classList.remove(trueStyle);
     64         classList.add(falseStyle);
     65     }
     66 }
     67 
     68 // Sorts the rows in a table lexicographically by the content of a specific column
     69 function sortTable(header, columnIndex, columns) {
     70     var container = header.parentElement;
     71     var descending = header.classList.contains(sortAsc);
     72     container.querySelectorAll("div.table-header").forEach(
     73         function(header) {
     74             header.classList.remove(sortAsc);
     75             header.classList.remove(sortDesc);
     76         }
     77     )
     78     var cells = container.children;
     79     var rows = [];
     80     for (var i = columns; i < cells.length; i += columns) {
     81         rows.push(Array.prototype.slice.call(cells, i, i + columns));
     82     }
     83     var comparator = function(a, b) {
     84         var ka = makeComparable(a[columnIndex].textContent);
     85         var kb = makeComparable(b[columnIndex].textContent);
     86         if (ka < kb)
     87             return descending ? 1 : -1;
     88         if (ka > kb)
     89             return descending ? -1 : 1;
     90         return 0;
     91     };
     92     var sorted = rows.sort(comparator);
     93     var visible = 0;
     94     sorted.forEach(function(row) {
     95         if (row[0].style.display !== 'none') {
     96             var isEvenRow = visible++ % 2 === 0;
     97         }
     98         row.forEach(function(cell) {
     99             toggleStyle(cell.classList, isEvenRow, evenRowColor, oddRowColor);
    100             container.appendChild(cell);
    101         })
    102     });
    103     toggleStyle(header.classList, descending, sortDesc, sortAsc);
    104 }
    105 
    106 // Toggles the visibility of a table category in all tables in a page
    107 function toggleGlobal(checkbox, selected, columns) {
    108     const display = checkbox.checked ? '' : 'none';
    109     const selectOther = selected === "other";
    110     const selectAll = selected === "all";
    111     if (selectAll) {
    112         document.querySelectorAll('.checkboxes input[type="checkbox"]').forEach(c => {
    113             c.checked = checkbox.checked;
    114         });
    115     }
    116     document.querySelectorAll("div.table-tabs").forEach(t => {
    117         const id = t.parentElement.getAttribute("id");
    118         const selectedClass = id + "-tab" + (selectOther ? "" : selected);
    119         var visible = 0;
    120         t.parentElement.querySelectorAll('div.' + id)
    121             .forEach(function(elem) {
    122                 if (selectAll
    123                     || (!selectOther && elem.classList.contains(selectedClass))
    124                     || (selectOther && elem.className.indexOf(selectedClass) < 0)) {
    125                     elem.style.display = display;
    126                 }
    127                 if (elem.style.display === '') {
    128                     var isEvenRow = visible++ % (columns * 2) < columns;
    129                     toggleStyle(elem.classList, isEvenRow, evenRowColor, oddRowColor);
    130                 }
    131             });
    132         var displaySection = visible === 0 ? 'none' : '';
    133         t.parentElement.style.display = displaySection;
    134         document.querySelector("li#contents-" + id).style.display = displaySection;
    135     })
    136 }
    137 
    138 // Shows the elements of a table belonging to a specific category
    139 function show(tableId, selected, columns) {
    140     if (tableId !== selected) {
    141         document.querySelectorAll('div.' + tableId + ':not(.' + selected + ')')
    142             .forEach(function(elem) {
    143                 elem.style.display = 'none';
    144             });
    145     }
    146     document.querySelectorAll('div.' + selected)
    147         .forEach(function(elem, index) {
    148             elem.style.display = '';
    149             var isEvenRow = index % (columns * 2) < columns;
    150             toggleStyle(elem.classList, isEvenRow, evenRowColor, oddRowColor);
    151         });
    152     updateTabs(tableId, selected);
    153 }
    154 
    155 function updateTabs(tableId, selected) {
    156     document.getElementById(tableId + '.tabpanel')
    157         .setAttribute('aria-labelledby', selected);
    158     document.querySelectorAll('button[id^="' + tableId + '"]')
    159         .forEach(function(tab, index) {
    160             if (selected === tab.id || (tableId === selected && index === 0)) {
    161                 tab.className = activeTableTab;
    162                 tab.setAttribute('aria-selected', true);
    163                 tab.setAttribute('tabindex',0);
    164             } else {
    165                 tab.className = tableTab;
    166                 tab.setAttribute('aria-selected', false);
    167                 tab.setAttribute('tabindex',-1);
    168             }
    169         });
    170 }
    171 
    172 function switchTab(e) {
    173     var selected = document.querySelector('[aria-selected=true]');
    174     if (selected) {
    175         if ((e.keyCode === 37 || e.keyCode === 38) && selected.previousSibling) {
    176             // left or up arrow key pressed: move focus to previous tab
    177             selected.previousSibling.click();
    178             selected.previousSibling.focus();
    179             e.preventDefault();
    180         } else if ((e.keyCode === 39 || e.keyCode === 40) && selected.nextSibling) {
    181             // right or down arrow key pressed: move focus to next tab
    182             selected.nextSibling.click();
    183             selected.nextSibling.focus();
    184             e.preventDefault();
    185         }
    186     }
    187 }
    188 
    189 var updateSearchResults = function() {};
    190 
    191 function indexFilesLoaded() {
    192     return moduleSearchIndex
    193         && packageSearchIndex
    194         && typeSearchIndex
    195         && memberSearchIndex
    196         && tagSearchIndex;
    197 }
    198 // Copy the contents of the local snippet to the clipboard
    199 function copySnippet(button) {
    200     copyToClipboard(button.nextElementSibling.innerText);
    201     switchCopyLabel(button, button.firstElementChild);
    202 }
    203 function copyToClipboard(content) {
    204     var textarea = document.createElement("textarea");
    205     textarea.style.height = 0;
    206     document.body.appendChild(textarea);
    207     textarea.value = content;
    208     textarea.select();
    209     document.execCommand("copy");
    210     document.body.removeChild(textarea);
    211 }
    212 function resetInput(input, event, blur) {
    213     if (input.value) {
    214         input.value = "";
    215         input.dispatchEvent(new InputEvent("input"));
    216     } else if (blur) {
    217         input.blur();
    218     }
    219     event.preventDefault();
    220 }
    221 function isInput(elem) {
    222     return elem instanceof HTMLInputElement && elem.type === "text";
    223 }
    224 function switchCopyLabel(button, span) {
    225     var copied = span.getAttribute("data-copied");
    226     button.classList.add("visible");
    227     var initialLabel = span.innerHTML;
    228     span.innerHTML = copied;
    229     setTimeout(function() {
    230         button.classList.remove("visible");
    231         setTimeout(function() {
    232             if (initialLabel !== copied) {
    233                 span.innerHTML = initialLabel;
    234             }
    235         }, 100);
    236     }, 1900);
    237 }
    238 function makeFilterWidget(sidebar, updateToc) {
    239     if (!sidebar) {
    240         return null;
    241     }
    242     const filterInput = sidebar.querySelector("input.filter-input");
    243     const resetInput = sidebar.querySelector("input.reset-filter");
    244     sidebar.addEventListener("keydown", e => {
    245         if (e.ctrlKey || e.altKey || e.metaKey) {
    246             return;
    247         }
    248         if (e.key === "ArrowUp" || e.key === "ArrowDown") {
    249             handleTocFocus(e);
    250         } else if (filterInput && e.target !== filterInput) {
    251             if (e.key === "Enter" && isTocLink(sidebar, e.target)) {
    252                 filterInput.value = "";
    253                 filterInput.dispatchEvent(new InputEvent("input"));
    254             } else if (e.key.length === 1 || e.key === "Backspace") {
    255                 filterInput.focus();
    256             }
    257         }
    258     });
    259     if (filterInput) {
    260         filterInput.removeAttribute("disabled");
    261         filterInput.setAttribute("autocapitalize", "off");
    262         filterInput.value = "";
    263         filterInput.addEventListener("input", function(e) {
    264             resetInput.style.visibility = filterInput.value ? "visible" : "hidden";
    265             const pattern = filterInput.value ? filterInput.value.trim()
    266                 .replace(/[\[\]{}()*+?.\\^$|]/g, '\\$&')
    267                 .replace(/\s+/g, ".*") : "";
    268             const filter = new RegExp(pattern, "i");
    269             sidebar.querySelectorAll("ol.toc-list li").forEach((li) => {
    270                 if (filter.test(li.innerText)) {
    271                     // li.removeAttribute("style");
    272                     const selfMatch = filter.test(li.firstElementChild.innerText);
    273                     li.style.display = "block";
    274                     li.firstElementChild.style.opacity =  selfMatch ? "100%" : "70%";
    275                     li.firstElementChild.tabIndex = selfMatch ? 0 : -1;
    276                 } else {
    277                     li.style.display = "none";
    278                 }
    279             });
    280             updateToc();
    281         });
    282     }
    283     if (resetInput) {
    284         resetInput.removeAttribute("disabled");
    285         resetInput.addEventListener("click", (e) => {
    286             filterInput.value = "";
    287             filterInput.focus();
    288             filterInput.dispatchEvent(new InputEvent("input"));
    289         });
    290     }
    291     function handleTocFocus(event) {
    292         let links = Array.from(sidebar.querySelectorAll("ol > li > a"))
    293             .filter(link => link.offsetParent && link.tabIndex === 0);
    294         let current = links.indexOf(document.activeElement);
    295         if (event.key === "ArrowUp") {
    296             if (current > 0) {
    297                 links[current - 1].focus({focusVisible: true});
    298             } else if (filterInput) {
    299                 filterInput.focus();
    300             }
    301         } else if (event.key === "ArrowDown" && current < links.length - 1) {
    302             links[current + 1].focus({focusVisible: true});
    303         }
    304         event.preventDefault();
    305     }
    306     function isTocLink(sidebar, elem) {
    307         let links = Array.from(sidebar.querySelectorAll("ol > li > a"))
    308             .filter(link => link.offsetParent && link.tabIndex === 0);
    309         return links.indexOf(elem) > -1;
    310     }
    311     return sidebar;
    312 }
    313 
    314 function setTopMargin() {
    315     // Dynamically set scroll margin to accomodate for draft header
    316     var headerHeight = Math.ceil(document.querySelector("header").offsetHeight);
    317     document.querySelector(":root")
    318         .style.setProperty("--nav-height", headerHeight + "px");
    319 }
    320 document.addEventListener("readystatechange", (e) => {
    321     if (document.readyState === "interactive") {
    322         setTopMargin();
    323     }
    324     if (sessionStorage.getItem("sidebar") === "hidden") {
    325         const sidebar = document.querySelector(".main-grid nav.toc");
    326         if (sidebar) sidebar.classList.add("hide-sidebar");
    327     }
    328 });
    329 document.addEventListener("DOMContentLoaded", function(e) {
    330     setTopMargin();
    331     // Make sure current element is visible in breadcrumb navigation on small displays
    332     const subnav = document.querySelector("ol.sub-nav-list");
    333     if (subnav && subnav.lastElementChild) {
    334         subnav.lastElementChild.scrollIntoView({ behavior: "instant", inline: "start", block: "nearest" });
    335     }
    336     const keymap = new Map();
    337     const searchInput = document.getElementById("search-input")
    338                    || document.getElementById("page-search-input");
    339     if (searchInput) {
    340         searchInput.addEventListener("focus", collapse);
    341         keymap.set("/", searchInput);
    342     }
    343     const filterInput = document.querySelector("input.filter-input");
    344     if (filterInput) {
    345         keymap.set(".", filterInput);
    346     }
    347     // Clone TOC sidebar to header for mobile navigation
    348     const navbar = document.querySelector("div#navbar-top");
    349     const sidebar = document.querySelector(".main-grid nav.toc");
    350     const main = document.querySelector(".main-grid main");
    351     const mainnav = navbar.querySelector("ul.nav-list");
    352     const toggleButton = document.querySelector("button#navbar-toggle-button");
    353     const tocMenu = sidebar ? sidebar.cloneNode(true) : null;
    354     makeFilterWidget(sidebar, updateToc);
    355     if (tocMenu) {
    356         navbar.appendChild(tocMenu);
    357         makeFilterWidget(tocMenu, updateToc);
    358         var menuInput = tocMenu.querySelector("input.filter-input");
    359     }
    360     document.addEventListener("keydown", (e) => {
    361         if (e.ctrlKey || e.altKey || e.metaKey) {
    362             return;
    363         }
    364         if (!isInput(e.target) && keymap.has(e.key)) {
    365             var elem = keymap.get(e.key);
    366             if (elem === filterInput && !elem.offsetParent) {
    367                 elem = getVisibleFilterInput(true);
    368             }
    369             elem.focus();
    370             elem.select();
    371             e.preventDefault();
    372         } else if (e.key === "Escape") {
    373             if (expanded) {
    374                 collapse();
    375                 e.preventDefault();
    376             } else if (e.target.id === "page-search-input") {
    377                 resetInput(e.target, e, false);
    378             } else if (isInput(e.target)) {
    379                 resetInput(e.target, e, true);
    380             } else {
    381                 var filter = getVisibleFilterInput(false);
    382                 if (filter && filter.value) {
    383                     resetInput(filterInput, e, true);
    384                 }
    385             }
    386         }
    387     });
    388     var expanded = false;
    389     var windowWidth;
    390     var bodyHeight;
    391     function collapse() {
    392         if (expanded) {
    393             mainnav.removeAttribute("style");
    394             if (tocMenu) {
    395                 tocMenu.removeAttribute("style");
    396                 if (filterInput) {
    397                     keymap.set(".", filterInput);
    398                 }
    399             }
    400             toggleButton.classList.remove("expanded")
    401             toggleButton.setAttribute("aria-expanded", "false");
    402             expanded = false;
    403         }
    404     }
    405     function expand() {
    406         expanded = true;
    407         mainnav.style.display = "block";
    408         mainnav.style.removeProperty("height");
    409         var maxHeight = window.innerHeight - subnav.offsetTop + 4;
    410         var expandedHeight = Math.min(maxHeight, mainnav.scrollHeight + 10);
    411         if (tocMenu) {
    412             tocMenu.style.display = "flex";
    413             expandedHeight = Math.min(maxHeight,
    414                 Math.max(expandedHeight, tocMenu.querySelector("div.toc-header").offsetHeight
    415                                        + tocMenu.querySelector("ol.toc-list").scrollHeight + 10));
    416             tocMenu.style.height = expandedHeight + "px";
    417             if (menuInput) {
    418                 keymap.set(".", menuInput);
    419             }
    420         }
    421         mainnav.style.height = expandedHeight + "px";
    422         toggleButton.classList.add("expanded");
    423         toggleButton.setAttribute("aria-expanded", "true");
    424         windowWidth = window.innerWidth;
    425     }
    426     function updateToc() {
    427         if (expanded) {
    428             expand();
    429         } else {
    430             prevHash = null;
    431             handleScroll();
    432         }
    433     }
    434     function getVisibleFilterInput(show) {
    435         if (sidebar && sidebar.offsetParent) {
    436             if (show) {
    437                 showSidebar();
    438             }
    439             return filterInput;
    440         } else {
    441             if (show) {
    442                 expand();
    443             }
    444             return menuInput;
    445         }
    446     }
    447     toggleButton.addEventListener("click", (e) => {
    448         if (expanded) {
    449             collapse();
    450         } else {
    451             expand();
    452         }
    453     });
    454     if (tocMenu) {
    455         tocMenu.querySelectorAll("a").forEach((link) => {
    456             link.addEventListener("click", collapse);
    457         });
    458     }
    459     document.querySelector("main").addEventListener("click", collapse);
    460     document.querySelectorAll("h1, h2, h3, h4, h5, h6")
    461         .forEach((hdr, idx) => {
    462             // Create anchor links for headers with an associated id attribute
    463             var id = hdr.parentElement.getAttribute("id") || hdr.getAttribute("id")
    464                 || (hdr.querySelector("a") && hdr.querySelector("a").getAttribute("id"));
    465             if (id) {
    466                 var template = document.createElement('template');
    467                 template.innerHTML =" <a href='#" + encodeURI(id) + "' class='anchor-link' aria-label='" + linkToSection
    468                     + "'><img src='" + pathtoroot + "resource-files/link.svg' alt='" + linkIcon +"' tabindex='0'"
    469                     + " width='16' height='16'></a>";
    470                 hdr.append(...template.content.childNodes);
    471             }
    472         });
    473     var sections;
    474     var scrollTimeout;
    475     var prevHash;
    476     function initSectionData() {
    477         bodyHeight = document.body.offsetHeight;
    478         sections = [{ id: "", top: 0 }].concat(Array.from(main.querySelectorAll(
    479                 "section[id], h2[id], h2 a[id], h3[id], h3 a[id], div[id]"))
    480             .filter((e) => {
    481                 return sidebar.querySelector("a[href=\"#" + encodeURI(e.getAttribute("id")) + "\"]") !== null
    482             }).map((e) => {
    483                 return {
    484                     id: e.getAttribute("id"),
    485                     top: e.offsetTop
    486                 };
    487             }));
    488     }
    489     function setScrollTimeout() {
    490         if (scrollTimeout) {
    491             clearTimeout(scrollTimeout);
    492         }
    493         scrollTimeout = setTimeout(() => {
    494             scrollTimeout = null;
    495         }, 100);
    496     }
    497     function handleScroll() {
    498         if (!sidebar || !sidebar.offsetParent || sidebar.classList.contains("hide-sidebar")) {
    499             return;
    500         }
    501         if (scrollTimeout) {
    502             setScrollTimeout();
    503             return;
    504         }
    505         var scrollTop = document.documentElement.scrollTop;
    506         var scrollHeight = document.documentElement.scrollHeight;
    507         var currHash = null;
    508         for (var i = 0; i < sections.length; i++) {
    509             var top = sections[i].top;
    510             var bottom = sections[i + 1] ? sections[i + 1].top : scrollHeight;
    511             if (top + ((bottom - top) / 2) > scrollTop || bottom > scrollTop + (window.innerHeight / 3)) {
    512                 currHash = "#" + encodeURI(sections[i].id);
    513                 break;
    514             }
    515         }
    516         if (currHash !== prevHash) {
    517             setSelected(currHash);
    518         }
    519     }
    520     function setSelected(hash) {
    521         var prev = sidebar.querySelector("a.current-selection");
    522         if (prev)
    523             prev.classList.remove("current-selection");
    524         prevHash = hash;
    525         if (hash) {
    526             var curr = sidebar.querySelector("ol.toc-list a[href=\"" + hash + "\"]");
    527             if (curr) {
    528                 curr.classList.add("current-selection");
    529                 curr.scrollIntoView({ behavior: "instant", block: "nearest" });
    530             }
    531         }
    532     }
    533     function hideSidebar() {
    534         sidebar.classList.add("hide-sidebar");
    535         sessionStorage.setItem("sidebar", "hidden");
    536     }
    537     function showSidebar() {
    538         sidebar.classList.remove("hide-sidebar");
    539         sessionStorage.removeItem("sidebar");
    540         initSectionData();
    541         handleScroll();
    542     }
    543     if (sidebar) {
    544         initSectionData();
    545         document.querySelectorAll("a[href^='#']").forEach((link) => {
    546             link.addEventListener("click", (e) => {
    547                 link.blur();
    548                 setScrollTimeout();
    549                 setSelected(link.getAttribute("href"));
    550             })
    551         });
    552         sidebar.querySelector("button.hide-sidebar").addEventListener("click", hideSidebar);
    553         sidebar.querySelector("button.show-sidebar").addEventListener("click", showSidebar);
    554         window.addEventListener("hashchange", (e) => {
    555             setScrollTimeout();
    556             const hash = e.newURL.indexOf("#");
    557             if (hash > -1) {
    558                 setSelected(e.newURL.substring(hash));
    559             }
    560         });
    561         if (document.location.hash) {
    562             setScrollTimeout();
    563             setSelected(document.location.hash);
    564         } else {
    565             handleScroll();
    566         }
    567         window.addEventListener("scroll", handleScroll);
    568     }
    569     // Resize handler
    570     new ResizeObserver((entries) => {
    571         if (expanded) {
    572             if (windowWidth !== window.innerWidth) {
    573                 collapse();
    574             } else {
    575                 expand();
    576             }
    577         }
    578         if (sections && document.body.offsetHeight !== bodyHeight) {
    579             initSectionData();
    580             prevHash = null;
    581             handleScroll();
    582         }
    583         setTopMargin();
    584     }).observe(document.body);
    585 });