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 14 ready: function () { 15 var self = this; 16 17 this.addToggleClick('mikio-sidebar-toggle', 'mikio-sidebar-collapse'); 18 this.addToggleClick('mikio-navbar-toggle', 'mikio-navbar-collapse'); 19 this.addDropdownClick('mikio-nav-dropdown', 'mikio-dropdown'); 20 this.indexmenuPatch(); 21 22 window.onresize = function () { 23 if (!this.queueResize) { 24 this.queueResize = true; 25 window.setTimeout(function () { 26 this.queueResize = false; 27 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 28 if (!elem.classList.contains('closed')) { 29 elem.classList.add('closed'); 30 } 31 }); 32 }, 100); 33 } 34 }; 35 36 // Mikio-Dropdown - Click 37 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 38 elem.addEventListener('click', function (event) { 39 event.stopPropagation(); 40 }); 41 }); 42 43 // Mikio-Dropdown - Close when clicked outside dropdown 44 Array.from(document.getElementsByTagName('body')).forEach(function (elem) { 45 elem.addEventListener('click', function (event) { 46 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 47 if (!elem.classList.contains('closed')) { 48 elem.classList.add('closed'); 49 } 50 }); 51 }); 52 }); 53 54 // Mikio-Navbar-Toggle - Fix 55 Array.from(document.getElementsByClassName('mikio-navbar-toggle')).forEach(function (elem) { 56 elem.classList.add('closed'); 57 }); 58 59 // Mikio-Dropdown - Fix 60 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 61 elem.classList.add('closed'); 62 }); 63 64 // Input File - Cleanup 65 Array.from(document.querySelectorAll('input[type=file]')).forEach(function (elem) { 66 var style = window.getComputedStyle(elem); 67 68 if (style.display != 'none') { 69 var parentElem = elem.parentElement; 70 var fileRect = elem.getBoundingClientRect(); 71 var parentRect = parentElem.getBoundingClientRect(); 72 var spanElem = document.createElement('span'); 73 74 elem.style.opacity = 0; 75 parentElem.style.position = 'relative'; 76 spanElem.innerHTML = 'Choose file...'; 77 spanElem.classList.add('mikio-input-file'); 78 spanElem.style.left = Math.floor(fileRect.left - parentRect.left) + 'px'; 79 spanElem.style.width = Math.floor(fileRect.right - fileRect.left) + 'px'; 80 mikio.insertAfter(spanElem, elem); 81 82 spanElem.addEventListener('click', function (event) { 83 if (event.target.parentElement.tagName.toLowerCase() != 'label') { 84 let sibling = mikio.getPrevSibling(event.target, 'input'); 85 if (typeof sibling !== 'undefined') { 86 sibling.click(); 87 } 88 } 89 }); 90 91 elem.addEventListener('change', function () { 92 if (this.files.length > 0) { 93 let mikioInput = mikio.getNextSibling(this, '.mikio-input-file'); 94 if (typeof mikioInput !== 'undefined') { 95 mikioInput.innerHTML = this.files[0].name; 96 } 97 } 98 }); 99 } 100 }); 101 102 // Input - Span (Placeholder) clear when typing 103 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) { 104 if (elem.value.length != 0) { 105 var sibling = mikio.getPrevSibling(elem, 'span'); 106 if (sibling) { 107 sibling.style.display = 'none'; 108 } 109 } 110 111 elem.addEventListener('keydown', function (event) { 112 var sibling = mikio.getPrevSibling(event.target, 'span'); 113 114 setTimeout(function () { 115 if (sibling) { 116 if (event.target.value != '') { 117 sibling.style.display = 'none'; 118 } else { 119 sibling.style.display = 'block'; 120 } 121 } 122 }, 50); 123 }); 124 }); 125 126 // Admin - Exit button 127 Array.from(document.querySelectorAll('a[rel="exit-admin"]')).forEach(function (elem) { 128 elem.addEventListener('click', function (event) { 129 event.preventDefault(); 130 131 var href = window.location.protocol + "//" + window.location.host + "/" + window.location.pathname; 132 133 var params = window.location.search; 134 if (params !== '') { 135 params = params.substr(1).split('&'); 136 if (params.length > 1) { 137 href += '?'; 138 params.forEach(function (p) { 139 if (p.substring(0, 3) == 'id=') { 140 href += p; 141 } 142 }); 143 } 144 } 145 146 window.location = href; 147 }); 148 }); 149 150 // Admin - Back button 151 Array.from(document.querySelectorAll('a[rel="exit-page"]')).forEach(function (elem) { 152 elem.addEventListener('click', function (event) { 153 event.preventDefault(); 154 155 var href = window.location.protocol + "//" + window.location.host + "/" + window.location.pathname; 156 157 var params = window.location.search; 158 if (params != '') { 159 params = params.substr(1).split('&'); 160 if (params.length > 1) { 161 href += '?'; 162 params.forEach(function (p) { 163 if (p.substring(0, 5) != 'page=') { 164 href += p + '&'; 165 } 166 }); 167 } 168 } 169 170 window.location = href; 171 }); 172 }); 173 174 // Admin - Resize large text blocks in tasks 175 Array.from(document.querySelectorAll('.admin_tasks span.prompt')).forEach(function (elem) { 176 if (elem.offsetHeight > 48) { 177 elem.style.fontSize = '80%'; 178 } 179 }); 180 181 // Media Manager - ui-resizable is always auto 182 var mediaChangedObserver = new MutationObserver(function (mutationsList) { 183 for (let mutation of mutationsList) { 184 if (mutation.type === 'childList') { 185 if (mutation.addedNodes) { 186 mutation.addedNodes.forEach(function (node) { 187 if (node.nodeName == 'LI') { 188 189 } 190 }); 191 } 192 } 193 194 if (mutation.type === 'attributes' && mutation.attributeName == 'style' && mutation.target && mutation.target.style.height) { 195 mutation.target.style.height = ''; 196 } 197 } 198 }); 199 200 var target = document.getElementById('mediamanager__page'); 201 if (target) { 202 mediaChangedObserver.observe(target, { attributes: true, childList: true, subtree: true }); 203 } 204 205 // Media Manager - file click 206 Array.from(document.querySelectorAll('#mediamanager__page .filelist')).forEach(function (elem) { 207 elem.addEventListener('click', function (event) { 208 var liElem = event.target.closest('li'); 209 if (liElem && event.target.closest('ul.thumbs')) { 210 var aElem = liElem.querySelector('dd.name a'); 211 if (aElem) aElem.click(); 212 } 213 }); 214 }); 215 216 // Popup Media Manager - clean file info 217 var mediaPopupFileInfoClean = function (elem) { 218 var file = { resolution: '', date: '', time: '', size: '' }; 219 220 var infoElem = elem.querySelector('span.info'); 221 if (infoElem) { 222 var infoText = infoElem.innerText.replace(/(<[^>]*>|[\(\)])/g, ''); 223 var detail = infoText.split(' '); 224 while (detail.length < 4) { 225 detail.unshift(''); 226 } 227 228 infoElem.innerHTML = detail[0] + '<br>' + detail[1] + ' ' + detail[2] + '<br>' + detail[3]; 229 } 230 231 Array.from(elem.querySelectorAll('img')).forEach(function (elem) { 232 elem.removeAttribute('width'); 233 elem.removeAttribute('height'); 234 }); 235 } 236 237 var mediaPopupObserver = new MutationObserver(function (mutationsList) { 238 for (let mutation of mutationsList) { 239 if (mutation.type === 'childList') { 240 if (mutation.addedNodes) { 241 mutation.addedNodes.forEach(function (node) { 242 if (node.nodeName == 'DIV') { 243 mediaPopupFileInfoClean(node); 244 } 245 }); 246 } 247 } 248 } 249 }); 250 251 var target = document.getElementById('media__content'); 252 if (target) { 253 Array.from(target.querySelectorAll('div.odd, div.even')).forEach(function (elem) { 254 mediaPopupFileInfoClean(elem); 255 }); 256 257 mediaPopupObserver.observe(target, { attributes: false, childList: true }); 258 } 259 260 if (typeof mikioFooterRun === "function") mikioFooterRun(); 261 262 // TESTING 263 264 var mediaChangedObserver = new MutationObserver(function (mutationsList) { 265 for (let mutation of mutationsList) { 266 if (mutation.type === 'attributes' && mutation.attributeName == 'href') { 267 if (self.mikioCSS != false) { 268 var elem = self.mikioCSS; 269 var prev = elem.href; 270 271 setTimeout(function () { 272 var url = new URL(prev); 273 var params = url.searchParams; 274 params.set('seed', new Date().getTime()); 275 url.search = params.toString(); 276 elem.href = url.toString(); 277 }, 500); 278 } 279 } 280 } 281 }); 282 283 var linkElements = document.getElementsByTagName('link'); 284 for (let element of linkElements) { 285 if (element.rel == 'stylesheet' && element.href) { 286 if (element.href.includes('/lib/exe/css.php')) { 287 mediaChangedObserver.observe(element, { attributes: true, childList: true, subtree: true }); 288 } else if (element.href.includes('/lib/tpl/mikio/css.php')) { 289 this.mikioCSS = element; 290 } 291 } 292 } 293 }, 294 295 insertAfter: function (newNode, existingNode) { 296 existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling); 297 }, 298 299 addToggleClick: function (elemToggle, elemCollapse) { 300 this.addEventListenerByClassName(elemToggle, 'click', function (event) { 301 event.preventDefault(); 302 event.stopPropagation(); 303 let nextSibling = mikio.getNextSibling(this, '.' + elemCollapse); 304 305 if (typeof nextSibling !== 'undefined') { 306 mikio.toggleCollapse(this, nextSibling); 307 } 308 }); 309 }, 310 311 addDropdownClick: function (elemToggle, elemCollapse) { 312 this.addEventListenerByClassName(elemToggle, 'click', function (event) { 313 event.preventDefault(); 314 event.stopPropagation(); 315 316 var dropdown = this.querySelector('.' + elemCollapse); 317 if (dropdown) { 318 mikio.toggleDropdown(dropdown); 319 } 320 }); 321 }, 322 323 addEventListenerByClassName: function (className, eventType, callback) { 324 Array.from(document.getElementsByClassName(className)).forEach(function (elem) { 325 elem.addEventListener(eventType, callback); 326 }); 327 }, 328 329 getNextSibling: function (elem, selector) { 330 var sibling = elem.nextElementSibling; 331 332 while (sibling) { 333 if (sibling.matches(selector)) return sibling; 334 sibling = sibling.nextElementSibling; 335 } 336 }, 337 338 getPrevSibling: function (elem, selector) { 339 var sibling = elem.previousElementSibling; 340 341 while (sibling) { 342 if (sibling.matches(selector)) return sibling; 343 sibling = sibling.previousElementSibling; 344 } 345 }, 346 347 toggleCollapse: function (objToggle, objCollapse) { 348 if (objToggle.classList.contains('closed')) { 349 objToggle.classList.remove('closed'); 350 objToggle.classList.add('open'); 351 var height = objCollapse.offsetHeight; 352 objCollapse.style.overflow = 'hidden'; 353 objCollapse.style.height = 0; 354 objCollapse.style.paddingTop = 0; 355 objCollapse.style.paddingBottom = 0; 356 objCollapse.style.marginTop = 0; 357 objCollapse.style.marginBottom = 0; 358 objCollapse.offsetHeight; 359 objCollapse.style.boxSizing = 'border-box'; 360 objCollapse.style.transitionProperty = "height, margin, padding"; 361 objCollapse.style.transitionDuration = '500ms'; 362 objCollapse.style.height = height + 'px'; 363 objCollapse.style.removeProperty('padding-top'); 364 objCollapse.style.removeProperty('padding-bottom'); 365 objCollapse.style.removeProperty('margin-top'); 366 objCollapse.style.removeProperty('margin-bottom'); 367 window.setTimeout(function () { 368 objCollapse.style.removeProperty('height'); 369 objCollapse.style.removeProperty('overflow'); 370 objCollapse.style.removeProperty('transition-duration'); 371 objCollapse.style.removeProperty('transition-property'); 372 objCollapse.style.removeProperty('box-sizing'); 373 }, 500); 374 } else { 375 objCollapse.style.transitionProperty = 'height, margin, padding'; 376 objCollapse.style.transitionDuration = '500ms'; 377 objCollapse.style.boxSizing = 'border-box'; 378 objCollapse.style.height = objCollapse.offsetHeight + 'px'; 379 objCollapse.offsetHeight; 380 objCollapse.style.overflow = 'hidden'; 381 objCollapse.style.height = 0; 382 objCollapse.style.paddingTop = 0; 383 objCollapse.style.paddingBottom = 0; 384 objCollapse.style.marginTop = 0; 385 objCollapse.style.marginBottom = 0; 386 window.setTimeout(function () { 387 objToggle.classList.add('closed'); 388 objToggle.classList.remove('open'); 389 objCollapse.style.removeProperty('height'); 390 objCollapse.style.removeProperty('padding-top'); 391 objCollapse.style.removeProperty('padding-bottom'); 392 objCollapse.style.removeProperty('margin-top'); 393 objCollapse.style.removeProperty('margin-bottom'); 394 objCollapse.style.removeProperty('overflow'); 395 objCollapse.style.removeProperty('transition-duration'); 396 objCollapse.style.removeProperty('transition-property'); 397 objCollapse.style.removeProperty('box-sizing'); 398 }, 500); 399 } 400 }, 401 402 403 toggleDropdown: function (objToggle) { 404 if (objToggle.classList.contains('closed')) { 405 objToggle.classList.remove('closed'); 406 } else { 407 objToggle.classList.add('closed'); 408 } 409 410 Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) { 411 if (!elem.classList.contains('closed') && elem != objToggle) { 412 elem.classList.add('closed'); 413 } 414 }); 415 }, 416 417 setHeroSubTitle: function (str) { 418 Array.from(document.getElementsByClassName('mikio-hero-subtitle')).forEach(function (elem) { 419 elem.innerHTML = str; 420 }); 421 }, 422 423 setHeroImage: function (str) { 424 var heroImages = document.getElementsByClassName('mikio-hero-image'); 425 426 if (heroImages.length > 0) { 427 Array.from(document.getElementsByClassName('mikio-hero-image')).forEach(function (elem) { 428 elem.style.backgroundImage = 'url(\'' + str + '\')'; 429 elem.classList.add('mikio-hero-image-resize'); 430 }); 431 } else { 432 Array.from(document.getElementsByClassName('mikio-hero-text')).forEach(function (elem) { 433 elem.insertAdjacentHTML('afterend', '<div class="mikio-hero-image mikio-hero-image-resize" style="background-image:url(\'' + str + '\');"></div>'); 434 }); 435 } 436 }, 437 438 setHeroColor: function (str) { 439 var colors = str.trim().replace(/ +(?= )/g, '').split(/(?!\(.*)\s(?![^(]*?\))/g); 440 if (colors.length > 0 && colors[0] != '') { 441 Array.from(document.getElementsByClassName('mikio-hero')).forEach(function (elem) { 442 elem.style.backgroundColor = colors[0]; 443 }); 444 445 if (colors.length > 1) { 446 Array.from(document.getElementsByClassName('mikio-hero-title')).forEach(function (elem) { 447 elem.style.color = colors[1]; 448 }); 449 } 450 451 if (colors.length > 2) { 452 Array.from(document.getElementsByClassName('mikio-hero-subtitle')).forEach(function (elem) { 453 elem.style.color = colors[2]; 454 }); 455 } 456 457 if (colors.length > 3) { 458 Array.from(document.getElementsByClassName('mikio-hero')).forEach(function (parentElem) { 459 Array.from(parentElem.querySelectorAll('.mikio-breadcrumbs ul li a')).forEach(function (elem) { 460 elem.style.color = colors[3]; 461 }); 462 463 Array.from(parentElem.querySelectorAll('.mikio-breadcrumbs ul li, .mikio-breadcrumbs ul li a')).forEach(function (elem) { 464 elem.style.color = colors[3]; 465 elem.onmouseover = function () { this.style.color = (colors.length > 4 ? colors[4] : 'initial'); }; 466 elem.onmouseout = function () { this.style.color = colors[3]; }; 467 }); 468 }); 469 } 470 } 471 }, 472 473 setTags: function (str) { 474 Array.from(document.getElementsByClassName('mikio-tags')).forEach(function (elem) { 475 elem.innerHTML = str; 476 }); 477 }, 478 479 hidePart: function (part) { 480 var selectorArray = { 481 topheader: '.mikio-page-topheader', 482 header: '.mikio-page-header', 483 contentheader: '.mikio-page-contentheader', 484 contentfooter: '.mikio-page-contentfooter', 485 sidebarheader: '.mikio-sidebar-left .mikio-sidebar-header', 486 sidebarfooter: '.mikio-sidebar-left .mikio-sidebar-footer', 487 rightsidebarheader: '.mikio-sidebar-right .mikio-sidebar-header', 488 rightsidebarfooter: '.mikio-sidebar-right .mikio-sidebar-footer', 489 footer: '.mikio-footer', 490 bottomfooter: '.mikio-page-bottomfooter', 491 navbar: '.mikio-navbar', 492 hero: '.mikio-hero' 493 }; 494 495 if (selectorArray.hasOwnProperty(part)) { 496 Array.from(document.querySelectorAll(selectorArray[part])).forEach(function (elem) { 497 elem.style.display = 'none'; 498 }); 499 } 500 }, 501 502 indexmenuPatch: function () { 503 window.setTimeout(function () { 504 Array.from(document.querySelectorAll('a.navSel')).forEach(function (elem) { 505 let prev = mikio.getPrevSibling(elem, 'img'); 506 if (prev) { 507 prev.style.opacity = 1; 508 } 509 }); 510 }, 50); 511 512 513 document.addEventListener('mouseover', function (event) { 514 const indexmenuClasses = ['nodeUrl', 'nodeSel', 'node']; 515 if ([...event.target.classList].some(className => indexmenuClasses.indexOf(className) !== -1)) { 516 let prev = mikio.getPrevSibling(event.target, 'img'); 517 if (prev) { 518 prev.style.opacity = 1; 519 } 520 } 521 }); 522 523 document.addEventListener('mouseout', function (event) { 524 const indexmenuClasses = ['nodeUrl', 'nodeSel', 'node']; 525 if ([...event.target.classList].some(className => indexmenuClasses.indexOf(className) !== -1)) { 526 let prev = mikio.getPrevSibling(event.target, 'img'); 527 if (prev) { 528 prev.style.opacity = ''; 529 } 530 } 531 }); 532 }, 533}; 534 535 536if (document.readyState != 'loading') { 537 mikio.ready(); 538} else { 539 document.addEventListener('DOMContentLoaded', function () { mikio.ready() }); 540} 541