1/** 2 * DokuWiki Mikio Template Javascript 3 * 4 * @link http://dokuwiki.org/template:mikio 5 * @author James Collins <james.collins@outlook.com.au> 6 * @license GPLv2 (http://www.gnu.org/licenses/gpl-2.0.html) 7 */ 8"use strict"; 9 10const mikio = { 11 queueResize: false, 12 mikioCSS: false, 13 stickyItems: [], 14 stickyOffset: 0, 15 stickyIndex: 2010, 16 darkMode: '', 17 18 ready: function () { 19 const updateStickyScroll = function () { 20 self.stickyItems.forEach((item) => { 21 // noinspection JSDeprecatedSymbols 22 if ((window.scrollY || window.pageYOffset) > item.offsetYTop) { 23 if (item.element.style.position !== 'fixed') { 24 let site = document.getElementById('dokuwiki__site'); 25 site.style.paddingTop = ((parseInt(site.style.paddingTop) || 0) + item.element.offsetHeight) + 'px'; 26 27 item.element.style.position = 'fixed'; 28 item.element.style.top = self.stickyOffset + 'px'; 29 item.element.style.zIndex = self.stickyIndex; 30 31 self.stickyOffset += item.element.offsetHeight; 32 self.stickyIndex--; 33 } 34 } else { 35 if (item.element.style.position === 'fixed') { 36 let site = document.getElementById('dokuwiki__site'); 37 site.style.paddingTop = ((parseInt(site.style.paddingTop) || 0) - item.element.offsetHeight) + 'px'; 38 self.stickyOffset -= item.element.offsetHeight; 39 self.stickyIndex++; 40 41 item.element.style.position = 'relative'; 42 item.element.style.top = null; 43 item.element.style.zIndex = null; 44 } 45 } 46 }); 47 }; 48 const self = this; 49 50 this.initDarkMode(); 51 this.addToggleClick('mikio-sidebar-toggle', 'mikio-sidebar-collapse'); 52 this.addToggleClick('mikio-navbar-toggle', 'mikio-navbar-collapse'); 53 this.addDropdownClick('mikio-nav-dropdown', 'mikio-dropdown'); 54 this.indexmenuPatch(); 55 this.typeahead(); 56 57 const updateStickyItems = function () { 58 window.removeEventListener('scroll', updateStickyScroll); 59 60 const stickyElements = document.getElementsByClassName('mikio-sticky'); 61 self.stickyItems = []; 62 if (stickyElements && stickyElements.length > 0) { 63 const stickyOffset = stickyElements[0].offsetTop; 64 let stickyHeightCount = stickyOffset; 65 66 [].forEach.call(stickyElements, (item) => { 67 let top = stickyOffset; 68 if (item.offsetTop - stickyHeightCount > stickyHeightCount) { 69 top = stickyHeightCount; 70 } 71 72 self.stickyItems.push({ 73 element: item, 74 offsetYTop: top, 75 debugItemTop: item.offsetTop, 76 debugOffset: stickyOffset, 77 debugHeight: stickyHeightCount 78 }); 79 stickyHeightCount += item.offsetHeight; 80 }); 81 82 window.addEventListener('scroll', updateStickyScroll); 83 updateStickyScroll(); 84 } 85 }; 86 87 88 updateStickyItems(); 89 90 window.onresize = function () { 91 if (!this.queueResize) { 92 this.queueResize = true; 93 const self = this; 94 window.setTimeout(function () { 95 self.queueResize = false; 96 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 97 if (!elem.classList.contains('closed')) { 98 elem.classList.add('closed'); 99 } 100 }); 101 102 updateStickyItems(); 103 }, 100); 104 } 105 }; 106 107 // Mikio-Dropdown - Click 108 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 109 elem.addEventListener('click', function (event) { 110 event.stopPropagation(); 111 }); 112 }); 113 114 // Mikio-Dropdown - Close when clicked outside dropdown 115 Array.from(document.getElementsByTagName('body')).forEach(function (elem) { 116 elem.addEventListener('click', function () { 117 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 118 if (!elem.classList.contains('closed')) { 119 elem.classList.add('closed'); 120 } 121 }); 122 }); 123 }); 124 125 // Mikio-Navbar-Toggle - Fix 126 Array.from(document.getElementsByClassName('mikio-navbar-toggle')).forEach(function (elem) { 127 elem.classList.add('closed'); 128 }); 129 130 // Mikio-Dropdown - Fix 131 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 132 elem.classList.add('closed'); 133 }); 134 135 // Input File - Cleanup 136 Array.from(document.querySelectorAll('input[type=file]')).forEach(function (elem) { 137 const style = window.getComputedStyle(elem); 138 139 if (style.display !== 'none') { 140 const parentElem = elem.parentElement; 141 const fileRect = elem.getBoundingClientRect(); 142 const parentRect = parentElem.getBoundingClientRect(); 143 const spanElem = document.createElement('span'); 144 145 elem.style.opacity = '0'; 146 parentElem.style.position = 'relative'; 147 spanElem.innerHTML = 'Choose file...'; 148 spanElem.classList.add('mikio-input-file'); 149 spanElem.style.left = Math.floor(fileRect.left - parentRect.left) + 'px'; 150 spanElem.style.width = Math.floor(fileRect.right - fileRect.left) + 'px'; 151 mikio.insertAfter(spanElem, elem); 152 153 spanElem.addEventListener('click', function (event) { 154 if (event.target.parentElement.tagName.toLowerCase() !== 'label') { 155 let sibling = mikio.getPrevSibling(event.target, 'input'); 156 if (typeof sibling !== 'undefined') { 157 sibling.click(); 158 } 159 } 160 }); 161 162 elem.addEventListener('change', function () { 163 if (this.files.length > 0) { 164 let mikioInput = mikio.getNextSibling(this, '.mikio-input-file'); 165 if (typeof mikioInput !== 'undefined') { 166 mikioInput.innerHTML = this.files[0].name; 167 } 168 } 169 }); 170 } 171 }); 172 173 // Input - Span (Placeholder) clear when typing 174 Array.from(document.querySelectorAll('.mikio.dokuwiki .mode_login fieldset label.block input.edit, .mikio.dokuwiki .mode_denied fieldset label.block input.edit')).forEach(function (elem) { 175 if (elem.value.length !== 0) { 176 const sibling = mikio.getPrevSibling(elem, 'span'); 177 if (sibling) { 178 sibling.style.display = 'none'; 179 } 180 } 181 182 elem.addEventListener('keydown', function (event) { 183 const sibling = mikio.getPrevSibling(event.target, 'span'); 184 185 setTimeout(function () { 186 if (sibling) { 187 if (event.target.value !== '') { 188 sibling.style.display = 'none'; 189 } else { 190 sibling.style.display = 'block'; 191 } 192 } 193 }, 50); 194 }); 195 }); 196 197 // Admin - Exit button 198 Array.from(document.querySelectorAll('a[rel="exit-admin"]')).forEach(function (elem) { 199 elem.addEventListener('click', function (event) { 200 event.preventDefault(); 201 202 let href = window.location.protocol + "//" + window.location.host + "/" + window.location.pathname; 203 204 let params = window.location.search; 205 if (params !== '') { 206 params = params.substring(1).split('&'); 207 if (params.length > 1) { 208 href += '?'; 209 params.forEach(function (p) { 210 if (p.substring(0, 3) === 'id=') { 211 href += p; 212 } 213 }); 214 } 215 } 216 217 window.location = href; 218 }); 219 }); 220 221 // Admin - Back button 222 Array.from(document.querySelectorAll('a[rel="exit-page"]')).forEach(function (elem) { 223 elem.addEventListener('click', function (event) { 224 event.preventDefault(); 225 226 let href = window.location.protocol + "//" + window.location.host + "/" + window.location.pathname; 227 228 let params = window.location.search; 229 if (params !== '') { 230 params = params.substring(1).split('&'); 231 if (params.length > 1) { 232 href += '?'; 233 params.forEach(function (p) { 234 if (p.substring(0, 5) !== 'page=') { 235 href += p + '&'; 236 } 237 }); 238 } 239 } 240 241 window.location = href; 242 }); 243 }); 244 245 // Admin - Resize large text blocks in tasks 246 Array.from(document.querySelectorAll('.admin_tasks span.prompt')).forEach(function (elem) { 247 if (elem.offsetHeight > 48) { 248 elem.style.fontSize = '80%'; 249 } 250 }); 251 252 let target = document.getElementById('mediamanager__page'); 253 if (target) { 254 // Media Manager - ui-resizable is always auto 255 const mediaChangedObserver = new MutationObserver(function (mutationsList) { 256 for (let mutation of mutationsList) { 257 if (mutation.type === 'childList') { 258 if (mutation.addedNodes) { 259 mutation.addedNodes.forEach(function (node) { 260 if (node.nodeName === 'LI') { 261 262 } 263 }); 264 } 265 } 266 267 if (mutation.type === 'attributes' && mutation.attributeName === 'style' && mutation.target && mutation.target.style.height) { 268 mutation.target.style.height = ''; 269 } 270 } 271 }); 272 273 mediaChangedObserver.observe(target, {attributes: true, childList: true, subtree: true}); 274 } 275 276 // Media Manager - file click 277 Array.from(document.querySelectorAll('#mediamanager__page .filelist')).forEach(function (elem) { 278 elem.addEventListener('click', function (event) { 279 const liElem = event.target.closest('li'); 280 if (liElem && event.target.closest('ul.thumbs')) { 281 const aElem = liElem.querySelector('dd.name a'); 282 if (aElem) aElem.click(); 283 } 284 }); 285 }); 286 287 // Popup Media Manager - clean file info 288 const mediaPopupFileInfoClean = function (elem) { 289 // var file = { resolution: '', date: '', time: '', size: '' }; 290 291 const infoElem = elem.querySelector('span.info'); 292 if (infoElem) { 293 const infoText = infoElem.innerText.replace(/(<[^>]*>|[()])/g, ''); 294 const detail = infoText.split(' '); 295 while (detail.length < 4) { 296 detail.unshift(''); 297 } 298 299 infoElem.innerHTML = detail[0] + '<br>' + detail[1] + ' ' + detail[2] + '<br>' + detail[3]; 300 } 301 302 Array.from(elem.querySelectorAll('img')).forEach(function (elem) { 303 elem.removeAttribute('width'); 304 elem.removeAttribute('height'); 305 }); 306 } 307 308 target = document.getElementById('media__content'); 309 if (target) { 310 Array.from(target.querySelectorAll('div.odd, div.even')).forEach(function (elem) { 311 mediaPopupFileInfoClean(elem); 312 }); 313 314 const mediaPopupObserver = new MutationObserver(function (mutationsList) { 315 for (let mutation of mutationsList) { 316 if (mutation.type === 'childList') { 317 if (mutation.addedNodes) { 318 mutation.addedNodes.forEach(function (node) { 319 if (node.nodeName === 'DIV') { 320 mediaPopupFileInfoClean(node); 321 } 322 }); 323 } 324 } 325 } 326 }); 327 328 mediaPopupObserver.observe(target, {attributes: false, childList: true}); 329 } 330 331 // noinspection JSUnresolvedReference 332 if (window.mikioFooterRun && typeof window.mikioFooterRun === "function") window.mikioFooterRun(); 333 334 const linkElements = document.getElementsByTagName('link'); 335 for (let element of linkElements) { 336 if (element.rel === 'stylesheet' && element.href) { 337 if (element.href.includes('/lib/exe/css.php')) { 338 const mediaChangedObserver = new MutationObserver(function (mutationsList) { 339 for (let mutation of mutationsList) { 340 if (mutation.type === 'attributes' && mutation.attributeName === 'href') { 341 if (self.mikioCSS !== false) { 342 let elem = self.mikioCSS; 343 let prev = elem.href; 344 345 setTimeout(function () { 346 const url = new URL(prev); 347 const params = url.searchParams; 348 params.set('seed', new Date().getTime().toString()); 349 url.search = params.toString(); 350 elem.href = url.toString(); 351 }, 500); 352 } 353 } 354 } 355 }); 356 357 mediaChangedObserver.observe(element, {attributes: true, childList: true, subtree: true}); 358 } else if (element.href.includes('/lib/tpl/mikio/css.php')) { 359 this.mikioCSS = element; 360 } 361 } 362 } 363 364 // Update color text field when selector changes 365 let colorSelectorInputs = document.querySelectorAll('div.mikio-color-picker input[type="color"]'); 366 colorSelectorInputs.forEach(input => { 367 input.addEventListener('input', () => { 368 let colorTextInput = document.querySelector(`div.mikio-color-picker input[for="${input.id}"]`); 369 if (colorTextInput) { 370 colorTextInput.value = input.value; 371 } 372 }); 373 }); 374 375 let colorTextInputs = document.querySelectorAll('div.mikio-color-picker input[type="text"]'); 376 colorTextInputs.forEach(input => { 377 input.addEventListener('blur', () => { 378 const id = input.getAttribute('for'); 379 let colorSelectorInput = document.querySelector(`div.mikio-color-picker input[id="${id}"]`); 380 if (colorSelectorInput) { 381 colorSelectorInput.value = this.colorToHex(input.value); 382 } 383 }); 384 }); 385 }, 386 387 initDarkMode: function () { 388 const showLightDark = document.querySelector('.mikio-darklight-button') != null; 389 if (showLightDark === true) { 390 let setting = this.getCookie('lightDarkToggle'); 391 if (setting === 'dark' || setting === 'light' || setting === 'auto') { 392 this.darkMode = setting; 393 } 394 395 if (document.querySelector('.mikio-auto-darklight') == null && setting === 'auto') { 396 this.darkMode = 'light'; 397 } 398 } else { 399 if (document.querySelector('.mikio-auto-darklight') != null) { 400 this.darkMode = 'auto'; 401 } 402 } 403 404 const self = this; 405 406 if (window.matchMedia) { 407 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { 408 self.updateDarkMode(); 409 }); 410 } 411 412 this.addEventListenerByClassName('mikio-darklight-button', 'click', function (event) { 413 event.preventDefault(); 414 event.stopPropagation(); 415 416 const autoAllowed = (document.querySelector('.mikio-iicon.mikio-darklight-auto') != null); 417 418 if (self.darkMode === 'light') { 419 self.darkMode = 'dark'; 420 } else if (self.darkMode === 'dark') { 421 if (autoAllowed === true) { 422 self.darkMode = 'auto'; 423 } else { 424 self.darkMode = 'light'; 425 } 426 } else if (self.darkMode === 'auto') { 427 self.darkMode = 'light'; 428 } else { 429 self.darkMode = 'dark'; 430 } 431 432 self.updateDarkMode(); 433 }); 434 435 this.updateDarkMode(); 436 }, 437 438 updateDarkMode: function () { 439 const html = document.querySelector('html'); 440 let themeMode = this.darkMode; 441 442 if (this.darkMode === 'auto') { 443 html.dataset.themeAuto = 'true'; 444 445 themeMode = 'light'; 446 if (window.matchMedia) { 447 let prefersColorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)'); 448 themeMode = prefersColorSchemeQuery.matches ? 'dark' : 'light'; 449 } 450 } else { 451 delete html.dataset.themeAuto; 452 } 453 454 console.log(this.darkMode); 455 456 if(themeMode === '') { 457 if(document.querySelector('body').classList.contains('mikio-default-dark')) { 458 themeMode = 'dark'; 459 } else { 460 themeMode = 'light'; 461 } 462 } 463 464 html.dataset.theme = `theme-${themeMode}`; 465 this.setCookie('lightDarkToggle', this.darkMode); 466 }, 467 468 insertAfter: function (newNode, existingNode) { 469 existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling); 470 }, 471 472 addToggleClick: function (elemToggle, elemCollapse) { 473 this.addEventListenerByClassName(elemToggle, 'click', function (event) { 474 event.preventDefault(); 475 event.stopPropagation(); 476 let nextSibling = mikio.getNextSibling(this, '.' + elemCollapse); 477 478 if (typeof nextSibling !== 'undefined') { 479 mikio.toggleCollapse(this, nextSibling); 480 } 481 }); 482 }, 483 484 addDropdownClick: function (elemToggle, elemCollapse) { 485 this.addEventListenerByClassName(elemToggle, 'click', function (event) { 486 event.preventDefault(); 487 event.stopPropagation(); 488 489 const dropdown = this.querySelector('.' + elemCollapse); 490 if (dropdown) { 491 mikio.toggleDropdown(dropdown); 492 } 493 }); 494 }, 495 496 addEventListenerByClassName: function (className, eventType, callback) { 497 Array.from(document.getElementsByClassName(className)).forEach(function (elem) { 498 elem.addEventListener(eventType, callback); 499 }); 500 }, 501 502 getNextSibling: function (elem, selector) { 503 let sibling = elem.nextElementSibling; 504 505 while (sibling) { 506 if (sibling.matches(selector)) return sibling; 507 sibling = sibling.nextElementSibling; 508 } 509 }, 510 511 getPrevSibling: function (elem, selector) { 512 let sibling = elem.previousElementSibling; 513 514 while (sibling) { 515 if (sibling.matches(selector)) return sibling; 516 sibling = sibling.previousElementSibling; 517 } 518 }, 519 520 toggleCollapse: function (objToggle, objCollapse) { 521 if (objToggle.classList.contains('closed')) { 522 objToggle.classList.remove('closed'); 523 objToggle.classList.add('open'); 524 const height = objCollapse.offsetHeight; 525 objCollapse.style.overflow = 'hidden'; 526 objCollapse.style.height = '0'; 527 objCollapse.style.paddingTop = '0'; 528 objCollapse.style.paddingBottom = '0'; 529 objCollapse.style.marginTop = '0'; 530 objCollapse.style.marginBottom = '0'; 531 objCollapse.offsetHeight; 532 objCollapse.style.boxSizing = 'border-box'; 533 objCollapse.style.transitionProperty = "height, margin, padding"; 534 objCollapse.style.transitionDuration = '500ms'; 535 objCollapse.style.height = height + 'px'; 536 objCollapse.style.removeProperty('padding-top'); 537 objCollapse.style.removeProperty('padding-bottom'); 538 objCollapse.style.removeProperty('margin-top'); 539 objCollapse.style.removeProperty('margin-bottom'); 540 window.setTimeout(function () { 541 objCollapse.style.removeProperty('height'); 542 objCollapse.style.removeProperty('overflow'); 543 objCollapse.style.removeProperty('transition-duration'); 544 objCollapse.style.removeProperty('transition-property'); 545 objCollapse.style.removeProperty('box-sizing'); 546 }, 500); 547 } else { 548 objCollapse.style.transitionProperty = 'height, margin, padding'; 549 objCollapse.style.transitionDuration = '500ms'; 550 objCollapse.style.boxSizing = 'border-box'; 551 objCollapse.style.height = objCollapse.offsetHeight + 'px'; 552 objCollapse.offsetHeight; 553 objCollapse.style.overflow = 'hidden'; 554 objCollapse.style.height = '0'; 555 objCollapse.style.paddingTop = '0'; 556 objCollapse.style.paddingBottom = '0'; 557 objCollapse.style.marginTop = '0'; 558 objCollapse.style.marginBottom = '0'; 559 window.setTimeout(function () { 560 objToggle.classList.add('closed'); 561 objToggle.classList.remove('open'); 562 objCollapse.style.removeProperty('height'); 563 objCollapse.style.removeProperty('padding-top'); 564 objCollapse.style.removeProperty('padding-bottom'); 565 objCollapse.style.removeProperty('margin-top'); 566 objCollapse.style.removeProperty('margin-bottom'); 567 objCollapse.style.removeProperty('overflow'); 568 objCollapse.style.removeProperty('transition-duration'); 569 objCollapse.style.removeProperty('transition-property'); 570 objCollapse.style.removeProperty('box-sizing'); 571 }, 500); 572 } 573 }, 574 575 576 toggleDropdown: function (objToggle) { 577 if (objToggle.classList.contains('closed')) { 578 objToggle.classList.remove('closed'); 579 } else { 580 objToggle.classList.add('closed'); 581 } 582 583 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 584 if (!elem.classList.contains('closed') && elem !== objToggle) { 585 elem.classList.add('closed'); 586 } 587 }); 588 }, 589 590 setHeroSubTitle: function (str) { 591 Array.from(document.getElementsByClassName('mikio-hero-subtitle')).forEach(function (elem) { 592 elem.innerHTML = str; 593 }); 594 }, 595 596 setHeroImage: function (str) { 597 const heroImages = document.getElementsByClassName('mikio-hero-image'); 598 599 if (heroImages.length > 0) { 600 Array.from(document.getElementsByClassName('mikio-hero-image')).forEach(function (elem) { 601 elem.style.backgroundImage = 'url(\'' + str + '\')'; 602 elem.classList.add('mikio-hero-image-resize'); 603 }); 604 } else { 605 Array.from(document.getElementsByClassName('mikio-hero-text')).forEach(function (elem) { 606 elem.insertAdjacentHTML('afterend', '<div class="mikio-hero-image mikio-hero-image-resize" style="background-image:url(\'' + str + '\');"></div>'); 607 }); 608 } 609 }, 610 611 setHeroColor: function (str) { 612 const colors = str.trim().replace(/ +(?= )/g, '').split(/(?!\(.*)\s(?![^(]*?\))/g); 613 if (colors.length > 0 && colors[0] !== '') { 614 Array.from(document.getElementsByClassName('mikio-hero')).forEach(function (elem) { 615 elem.style.backgroundColor = colors[0]; 616 }); 617 618 if (colors.length > 1) { 619 Array.from(document.getElementsByClassName('mikio-hero-title')).forEach(function (elem) { 620 elem.style.color = colors[1]; 621 }); 622 } 623 624 if (colors.length > 2) { 625 Array.from(document.getElementsByClassName('mikio-hero-subtitle')).forEach(function (elem) { 626 elem.style.color = colors[2]; 627 }); 628 } 629 630 if (colors.length > 3) { 631 Array.from(document.getElementsByClassName('mikio-hero')).forEach(function (parentElem) { 632 Array.from(parentElem.querySelectorAll('.mikio-breadcrumbs ul li a')).forEach(function (elem) { 633 elem.style.color = colors[3]; 634 }); 635 636 Array.from(parentElem.querySelectorAll('.mikio-breadcrumbs ul li, .mikio-breadcrumbs ul li a')).forEach(function (elem) { 637 elem.style.color = colors[3]; 638 elem.onmouseover = function () { this.style.color = (colors.length > 4 ? colors[4] : 'initial'); }; 639 elem.onmouseout = function () { this.style.color = colors[3]; }; 640 }); 641 }); 642 } 643 } 644 }, 645 646 setTags: function (str) { 647 Array.from(document.getElementsByClassName('mikio-tags')).forEach(function (elem) { 648 elem.innerHTML = str; 649 }); 650 }, 651 652 hidePart: function (part) { 653 const selectorArray = { 654 topheader: '.mikio-page-topheader', 655 header: '.mikio-page-header', 656 contentheader: '.mikio-page-contentheader', 657 contentfooter: '.mikio-page-contentfooter', 658 sidebarheader: '.mikio-sidebar-left .mikio-sidebar-header', 659 sidebarfooter: '.mikio-sidebar-left .mikio-sidebar-footer', 660 rightsidebarheader: '.mikio-sidebar-right .mikio-sidebar-header', 661 rightsidebarfooter: '.mikio-sidebar-right .mikio-sidebar-footer', 662 footer: '.mikio-footer', 663 bottomfooter: '.mikio-page-bottomfooter', 664 navbar: '.mikio-navbar', 665 hero: '.mikio-hero' 666 }; 667 668 if (selectorArray.hasOwnProperty(part)) { 669 Array.from(document.querySelectorAll(selectorArray[part])).forEach(function (elem) { 670 elem.style.display = 'none'; 671 }); 672 } 673 }, 674 675 indexmenuPatch: function () { 676 window.setTimeout(function () { 677 Array.from(document.querySelectorAll('a.navSel')).forEach(function (elem) { 678 let prev = mikio.getPrevSibling(elem, 'img'); 679 if (prev) { 680 prev.style.opacity = '1'; 681 } 682 }); 683 }, 50); 684 685 686 document.addEventListener('mouseover', function (event) { 687 const indexmenuClasses = ['nodeUrl', 'nodeSel', 'node']; 688 if ([...event.target.classList].some(className => indexmenuClasses.indexOf(className) !== -1)) { 689 let prev = mikio.getPrevSibling(event.target, 'img'); 690 if (prev) { 691 prev.style.opacity = '1'; 692 } 693 } 694 }); 695 696 document.addEventListener('mouseout', function (event) { 697 const indexmenuClasses = ['nodeUrl', 'nodeSel', 'node']; 698 if ([...event.target.classList].some(className => indexmenuClasses.indexOf(className) !== -1)) { 699 let prev = mikio.getPrevSibling(event.target, 'img'); 700 if (prev) { 701 prev.style.opacity = ''; 702 } 703 } 704 }); 705 }, 706 707 // Add typeahead support for quick seach. Taken from bootstrap3 theme. 708 typeahead: function () { 709 jQuery(".search_typeahead").typeahead({ 710 711 source: function (query, process) { 712 713 return jQuery.post(DOKU_BASE + 'lib/exe/ajax.php', 714 { 715 call: 'qsearch', 716 q: encodeURI(query) 717 }, 718 function (data) { 719 720 const results = []; 721 722 jQuery(data).find('a').each(function () { 723 724 const page = jQuery(this); 725 726 results.push({ 727 name: page.text(), 728 href: page.attr('href'), 729 title: page.attr('title'), 730 category: page.attr('title').replace(/:/g, ' : '), 731 }); 732 733 }); 734 735 return process(results); 736 737 }); 738 }, 739 740 itemLink: function (item) { 741 return item.href; 742 }, 743 744 itemTitle: function (item) { 745 return item.title; 746 }, 747 748 followLinkOnSelect: true, 749 autoSelect: false, 750 items: 10, 751 fitToElement: true, 752 delay: 500, 753 theme: 'bootstrap4', 754 755 }); 756 }, 757 758 getCookie: function (cname) { 759 let name = cname + "="; 760 let decodedCookie = decodeURIComponent(document.cookie); 761 let ca = decodedCookie.split(';'); 762 for (let i = 0; i < ca.length; i++) { 763 let c = ca[i]; 764 while (c.charAt(0) === ' ') { 765 c = c.substring(1); 766 } 767 if (c.indexOf(name) === 0) { 768 return c.substring(name.length, c.length); 769 } 770 } 771 return ""; 772 }, 773 774 setCookie: function (cname, cvalue, exdays) { 775 const d = new Date(); 776 d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); 777 let expires = "expires=" + d.toUTCString(); 778 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/;SameSite=Lax"; 779 }, 780 781 clearCookie: function (cname) { 782 document.cookie = cname + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;SameSite=Lax"; 783 }, 784 785 colorToHex: function (color) { 786 // Create a canvas element 787 let canvas = document.createElement('canvas'); 788 canvas.height = 1; 789 canvas.width = 1; 790 let ctx = canvas.getContext('2d'); 791 792 // Set the fillStyle to the color input 793 ctx.fillStyle = color; 794 ctx.fillRect(0, 0, 1, 1); 795 796 // Get the pixel data from the canvas 797 let data = ctx.getImageData(0, 0, 1, 1).data; 798 799 // Convert the RGB values to HEX 800 return '#' + ((1 << 24) + (data[0] << 16) + (data[1] << 8) + data[2]).toString(16).slice(1).toUpperCase(); 801 } 802}; 803 804if (document.readyState !== 'loading') { 805 mikio.ready(); 806} else { 807 document.addEventListener('DOMContentLoaded', function () { mikio.ready() }); 808} 809