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