1if (!Element.prototype.matches) { 2 Element.prototype.matches = 3 Element.prototype.msMatchesSelector || 4 Element.prototype.webkitMatchesSelector; 5} 6 7if (!Element.prototype.closest) { 8 Element.prototype.closest = function (s) { 9 let el = this; 10 11 do { 12 if (el.matches(s)) return el; 13 el = el.parentElement || el.parentNode; 14 } while (el !== null && el.nodeType === 1); 15 return null; 16 }; 17} 18 19function ub_hashHeaderScroll(scrollType = "auto", target = "", offset = 0) { 20 if (window.location.hash) { 21 const targetHeading = document.getElementById( 22 window.location.hash.slice(1) 23 ); 24 25 let probableHeaders; 26 27 try { 28 probableHeaders = document.elementsFromPoint(window.innerWidth / 2, 0); 29 } catch (e) { 30 probableHeaders = document.msElementsFromPoint(window.innerWidth / 2, 0); 31 } 32 33 const stickyHeaders = Array.prototype.slice 34 .call(probableHeaders) 35 .filter((e) => 36 ["fixed", "sticky"].includes(window.getComputedStyle(e).position) 37 ); 38 39 const stickyHeaderHeights = stickyHeaders.map((h) => h.offsetHeight); 40 41 const deficit = 42 targetHeading.getBoundingClientRect().y || 43 targetHeading.getBoundingClientRect().top; 44 45 switch (scrollType) { 46 default: 47 window.scrollBy(0, deficit); 48 break; 49 case "off": 50 window.scrollBy(0, deficit); 51 break; 52 case "auto": 53 window.scrollBy( 54 0, 55 deficit - 56 (stickyHeaders.length 57 ? Math.max.apply(Math, stickyHeaderHeights) 58 : 0) 59 ); 60 break; 61 case "fixedamount": 62 window.scrollBy(0, deficit - offset); 63 break; 64 case "namedelement": 65 window.scrollBy( 66 0, 67 deficit - 68 (document.querySelector(target) 69 ? document.querySelector(target).offsetHeight 70 : 0) 71 ); 72 break; 73 } 74 } 75} 76 77document.addEventListener("DOMContentLoaded", function () { 78 let instances = []; 79 if (document.getElementById("ub_table-of-contents-toggle-link")) { 80 instances.push(document.getElementById("ub_table-of-contents-toggle-link")); 81 } else { 82 instances = Array.prototype.slice.call( 83 document.getElementsByClassName("ub_table-of-contents-toggle-link") 84 ); 85 } 86 //also push ToC toggle icon instances here? 87 88 instances = instances.concat( 89 Array.prototype.slice.call( 90 document.getElementsByClassName( 91 "ub_table-of-contents-toggle-icon-container" 92 ) 93 ) 94 ); 95 96 instances.forEach((instance) => { 97 const block = instance.closest(".ub_table-of-contents"); 98 99 const tocContainer = block.querySelector(".ub_table-of-contents-container"); 100 const containerStyle = tocContainer.style; 101 102 const tocExtraContainer = block.querySelector( 103 ".ub_table-of-contents-extra-container" 104 ); 105 const extraContainerStyle = tocExtraContainer.style; 106 107 const tocMain = tocExtraContainer.parentNode; 108 const mainStyle = block.style; 109 110 const showButton = block.getAttribute("data-showtext") || "show"; 111 const hideButton = block.getAttribute("data-hidetext") || "hide"; 112 113 tocContainer.removeAttribute("style"); 114 115 let padding = 60; 116 117 function mobileEvent(mql) { 118 if (mql.matches) { 119 if (!tocMain.classList.contains("ub_table-of-contents-collapsed")) { 120 tocMain.classList.add("ub_table-of-contents-collapsed"); 121 if ( 122 instance.classList.contains("ub_table-of-contents-toggle-link") || 123 instance.id === "ub_table-of-contents-toggle-link" 124 ) { 125 instance.innerHTML = showButton; 126 } 127 tocContainer.classList.add("ub-hide"); 128 } 129 } else { 130 if (JSON.parse(tocMain.dataset.initiallyshow)) { 131 tocMain.classList.remove("ub_table-of-contents-collapsed"); 132 if ( 133 instance.classList.contains("ub_table-of-contents-toggle-link") || 134 instance.id === "ub_table-of-contents-toggle-link" 135 ) { 136 instance.innerHTML = hideButton; 137 } 138 tocContainer.classList.remove("ub-hide"); 139 } 140 } 141 } 142 143 let mobileQuery = window.matchMedia("(max-width: 800px)"); 144 145 if (JSON.parse(block.getAttribute("data-initiallyhideonmobile"))) { 146 mobileQuery.addListener(mobileEvent); 147 } 148 149 instance.addEventListener("click", function (event) { 150 event.preventDefault(); 151 const curWidth = block.offsetWidth; 152 153 if (block.classList.contains("ub_table-of-contents-collapsed")) { 154 //begin showing 155 tocExtraContainer.classList.remove("ub-hide"); 156 tocContainer.classList.remove("ub-hide"); 157 const targetHeight = tocExtraContainer.offsetHeight + padding / 2; //doesn't include padding 158 tocContainer.classList.add("ub-hiding"); 159 tocExtraContainer.classList.add("ub-hiding"); 160 mainStyle.width = `${curWidth}px`; //also take into account number of columns 161 162 setTimeout(() => { 163 mainStyle.width = "auto"; 164 block.classList.remove("ub_table-of-contents-collapsed"); 165 const fullWidth = getComputedStyle(block).width.slice(0, -2); 166 mainStyle.width = `${curWidth}px`; 167 168 setTimeout(() => { 169 Object.assign(containerStyle, { 170 height: `${targetHeight}px`, 171 width: "100px", 172 }); 173 Object.assign(extraContainerStyle, { 174 height: `${targetHeight}px`, 175 width: "100px", 176 }); 177 tocContainer.classList.remove("ub-hiding"); 178 tocExtraContainer.classList.remove("ub-hiding"); 179 180 mainStyle.width = `${fullWidth}px`; 181 182 setTimeout(() => { 183 tocContainer.style.width = `${fullWidth - padding}px`; 184 tocExtraContainer.style.width = `${fullWidth - padding}px`; 185 }, 50); 186 }, 50); 187 }, 50); 188 } else { 189 //begin hiding 190 mainStyle.width = `${block.offsetWidth}px`; 191 Object.assign(containerStyle, { 192 height: `${tocContainer.offsetHeight}px`, 193 width: `${tocContainer.offsetWidth}px`, 194 }); 195 Object.assign(extraContainerStyle, { 196 height: `${tocExtraContainer.offsetHeight}px`, 197 width: `${tocExtraContainer.offsetWidth}px`, 198 }); 199 200 setTimeout(() => { 201 tocContainer.classList.add("ub-hiding"); 202 Object.assign(containerStyle, { 203 height: "0", 204 width: "0", 205 }); 206 Object.assign(extraContainerStyle, { 207 height: "0", 208 width: "0", 209 }); 210 block.classList.add("ub_table-of-contents-collapsed"); 211 212 padding = 213 parseInt( 214 getComputedStyle(tocExtraContainer).paddingLeft.slice(0, -2) 215 ) + 216 parseInt( 217 getComputedStyle(tocExtraContainer).paddingRight.slice(0, -2) 218 ); 219 220 //measure width of toc title + toggle button, then use it as width of block 221 222 mainStyle.width = `${ 223 5 + 224 padding + 225 instance.closest(".ub_table-of-contents-header-container") 226 .scrollWidth 227 }px`; 228 }, 50); 229 } 230 231 if ( 232 instance.classList.contains("ub_table-of-contents-toggle-link") || 233 instance.id === "ub_table-of-contents-toggle-link" 234 ) { 235 instance.innerHTML = tocContainer.classList.contains("ub-hiding") 236 ? hideButton 237 : showButton; 238 } else { 239 if ( 240 instance.children[0].classList.contains( 241 "ub_table-of-contents-plus-part" 242 ) 243 ) { 244 instance.children[0].classList.toggle("ub_horizontal_bar"); 245 instance.children[0].classList.toggle("ub_vertical_bar"); 246 instance.children[1].classList.toggle("ub_vertical_bar"); 247 } else { 248 instance.children[0].classList.toggle("ub_asc_diagonal_bar"); 249 instance.children[0].classList.toggle("ub_desc_diagonal_bar"); 250 instance.children[1].classList.toggle("ub_asc_diagonal_bar"); 251 instance.children[1].classList.toggle("ub_desc_diagonal_bar"); 252 } 253 } 254 255 mobileQuery.removeListener(mobileEvent); 256 }); 257 258 tocContainer.addEventListener("transitionend", function () { 259 if (tocContainer.offsetHeight === 0) { 260 //hiding is done 261 tocContainer.classList.remove("ub-hiding"); 262 tocContainer.classList.add("ub-hide"); 263 tocExtraContainer.classList.remove("ub-hiding"); 264 tocExtraContainer.classList.add("ub-hide"); 265 if (containerStyle.display === "block") { 266 containerStyle.display = ""; 267 } 268 if (extraContainerStyle.display === "block") { 269 extraContainerStyle.display = ""; 270 } 271 mainStyle.minWidth = ""; 272 } 273 Object.assign(containerStyle, { 274 height: "", 275 width: "", 276 }); 277 Object.assign(extraContainerStyle, { 278 height: "", 279 width: "", 280 }); 281 mainStyle.width = ""; 282 }); 283 }); 284 if (window.location.hash) { 285 const sourceToC = document.querySelector(".ub_table-of-contents"); 286 if (sourceToC) { 287 const type = sourceToC.dataset.scrolltype; 288 const offset = 289 type === "fixedamount" ? sourceToC.dataset.scrollamount : 0; 290 const target = 291 type === "namedelement" ? sourceToC.dataset.scrolltarget : ""; 292 setTimeout(() => ub_hashHeaderScroll(type, target, offset), 50); 293 } 294 } 295}); 296 297window.onhashchange = function () { 298 const sourceToC = document.querySelector(".ub_table-of-contents"); 299 if (sourceToC) { 300 const type = sourceToC.dataset.scrolltype; 301 const offset = type === "fixedamount" ? sourceToC.dataset.scrollamount : 0; 302 const target = 303 type === "namedelement" ? sourceToC.dataset.scrolltarget : ""; 304 ub_hashHeaderScroll(type, target, offset); 305 } 306}; 307 308Array.prototype.slice 309 .call(document.querySelectorAll(".ub_table-of-contents-container li > a")) 310 .forEach((link) => { 311 link.addEventListener("click", (e) => { 312 const hashlessLink = link.href.replace(link.hash, ""); 313 const targetPageNumber = /[?&]page=\d+/g.exec(hashlessLink); 314 const currentPageNumber = /[?&]page=\d+/g.exec(window.location.search); 315 if ( 316 window.location.href.includes(hashlessLink) && 317 (currentPageNumber === null || 318 (targetPageNumber && currentPageNumber[0] === targetPageNumber[0])) 319 ) { 320 const tocData = link.closest(".ub_table-of-contents").dataset; 321 const type = tocData.scrolltype; 322 const offset = type === "fixedamount" ? tocData.scrollamount : 0; 323 const target = type === "namedelement" ? tocData.scrolltarget : ""; 324 e.preventDefault(); 325 history.pushState(null, "", link.hash); 326 ub_hashHeaderScroll(type, target, offset); 327 } 328 }); 329 }); 330 331function stickyTOC(element) { 332 function createStickyTOC() { 333 const tocPosition = element.dataset.sticky_toc_position; 334 const tocWidth = element.dataset.sticky_toc_width; 335 const buttonIcon = element.dataset.sticky_button_icon; 336 const buttonColor = element.dataset.sticky_button_color; 337 338 const stickyTOCWrapper = document.createElement("div"); 339 stickyTOCWrapper.classList.add("ub_sticky-toc-wrapper"); 340 stickyTOCWrapper.style.width = tocWidth + "px"; 341 if (Number(tocPosition) > 50) { 342 stickyTOCWrapper.classList.add("ub_sticky-toc-right"); 343 stickyTOCWrapper.style.right = 100 - Number(tocPosition) + "%"; 344 } else if (Number(tocPosition) < 50) { 345 stickyTOCWrapper.style.left = tocPosition + "%"; 346 stickyTOCWrapper.classList.add("ub_sticky-toc-left"); 347 } 348 349 const stickyTOCButton = document.createElement("button"); 350 stickyTOCButton.classList.add("ub_sticky-toc-button"); 351 stickyTOCButton.style.borderColor = buttonColor; 352 stickyTOCButton.innerHTML = buttonIcon; 353 354 stickyTOCWrapper.appendChild(stickyTOCButton); 355 356 const stickyTOCElement = element.cloneNode(true); 357 stickyTOCElement.classList.add("ub_sticky-toc"); 358 stickyTOCElement.classList.add("ub_sticky-toc-zoom-out"); 359 const closeStickyTOCElement = document.createElement("span"); 360 closeStickyTOCElement.classList.add("ub_close-sticky-button"); 361 closeStickyTOCElement.innerHTML = ` 362 <svg 363 width="20px" 364 height="20px"
365 viewBox="0 0 100 100" 366 xmlns="http://www.w3.org/2000/svg" 367 > 368 <path d="m50 2.5c-26.199 0-47.5 21.301-47.5 47.5s21.301 47.5 47.5 47.5 47.5-21.301 47.5-47.5-21.301-47.5-47.5-47.5zm24.898 62.301l-10.199 10.199-14.801-14.801-14.801 14.801-10.199-10.199 14.801-14.801-14.801-14.801 10.199-10.199 14.801 14.801 14.801-14.801 10.199 10.199-14.801 14.801z" /> 369 </svg> 370 `; 371 if (Number(tocPosition) >= 100) { 372 stickyTOCButton.style.transform = "translate(-100%,-50%)"; 373 } 374 if (Number(tocPosition) > 50) { 375 stickyTOCWrapper.style.right = 100 - Number(tocPosition) + "%"; 376 } 377 if (Number(tocPosition) === 50) { 378 stickyTOCWrapper.style.left = tocPosition + "%"; 379 stickyTOCWrapper.style.transform = "translate(-50%,-50%)"; 380 } 381 stickyTOCElement.appendChild(closeStickyTOCElement); 382 383 closeStickyTOCElement.addEventListener("click", () => { 384 stickyTOCElement.style.display = "none"; 385 stickyTOCButton.style.display = "block"; 386 stickyTOCButton.classList.remove("ub_sticky-toc-zoom-in"); 387 stickyTOCButton.classList.add("ub_sticky-toc-zoom-out"); 388 stickyTOCElement.classList.remove("ub_sticky-toc-zoom-out"); 389 stickyTOCElement.classList.add("ub_sticky-toc-zoom-in"); 390 }); 391 stickyTOCButton.addEventListener("click", () => { 392 stickyTOCElement.style.display = "grid"; 393 stickyTOCButton.style.display = "none"; 394 stickyTOCButton.classList.add("ub_sticky-toc-zoom-in"); 395 stickyTOCElement.classList.add("ub_sticky-toc-zoom-out"); 396 }); 397 stickyTOCWrapper.appendChild(stickyTOCElement); 398 return stickyTOCWrapper; 399 } 400 const createdStickyTOC = createStickyTOC(); 401 function handleIntersection(entries, observer) { 402 entries.forEach((entry) => { 403 const isHideOnMobile = element.dataset.hide_sticky_on_mobile === "true"; 404 const hideTOCOnMobile = isHideOnMobile && document.body.clientWidth < 681; 405 const isStickyOnDocument = document.querySelector( 406 ".ub_sticky-toc-wrapper" 407 ); 408 409 if (createdStickyTOC) { 410 if (entry.isIntersecting) { 411 if (isStickyOnDocument) { 412 document.body.removeChild(createdStickyTOC); 413 } 414 } else { 415 if (!hideTOCOnMobile) { 416 document.body.appendChild(createdStickyTOC); 417 } 418 } 419 } 420 }); 421 } 422 423 const options = { 424 root: null, 425 rootMargin: "0px", 426 threshold: 0, 427 }; 428 429 const observer = new IntersectionObserver(handleIntersection, options); 430 431 observer.observe(element); 432} 433 434document.addEventListener("DOMContentLoaded", () => { 435 const tableOfContents = document.querySelectorAll(".ub_table-of-contents"); 436 437 tableOfContents.forEach((element) => { 438 const isSticky = element.dataset.is_sticky === "true"; 439 if (isSticky) { 440 stickyTOC(element); 441 } 442 }); 443 // Link to divider block. 444 const dividers = document.querySelectorAll( 445 ".wp-block-ub-divider:not(.ub-divider-orientation-vertical)" 446 ); 447 if (tableOfContents.length > 0 && dividers.length > 0) { 448 dividers.forEach((divider) => { 449 let closestTOC = null; 450 let minDistance = Infinity; 451 452 tableOfContents.forEach((toc) => { 453 const isLinkedToDivider = 454 toc.getAttribute("data-linktodivider") === "true" ? true : false; 455 const isSticky = 456 toc.getAttribute("data-is_sticky") === "true" ? true : false; 457 458 if (!isLinkedToDivider || isSticky) { 459 return; 460 } 461 const dividerTop = divider.getBoundingClientRect().top; 462 const tocTop = toc.getBoundingClientRect().top; 463 const distance = Math.abs(dividerTop - tocTop); 464 if (distance < minDistance) { 465 minDistance = distance; 466 closestTOC = toc; 467 } 468 }); 469 470 if (closestTOC) { 471 const linkToTOC = document.createElement("a"); 472 linkToTOC.href = `#${closestTOC.getAttribute("id")}`; 473 linkToTOC.classList.add("ub-linked-to-toc"); 474 linkToTOC.innerText = "Table Of Contents"; 475 divider.appendChild(linkToTOC); 476 } 477 }); 478 } 479});
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.