xref: /template/mikio/assets/mikio.js (revision dea1f0889c905f728c3aee923c1b4f8f58f42372)
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        let setting = this.getCookie('lightDarkToggle');
381        if (setting == 'dark' || setting == 'light' || setting == 'auto') {
382            this.darkMode = setting;
383        }
384
385        var self = this;
386
387        if(window.matchMedia) {
388            window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
389                self.updateDarkMode();
390            });
391        }
392
393        this.addEventListenerByClassName('mikio-darklight-button', 'click', function (event) {
394            event.preventDefault();
395            event.stopPropagation();
396
397            const autoAllowed = (document.querySelector('.mikio-iicon.mikio-darklight-auto') != null);
398
399            if(self.darkMode == 'light') {
400                self.darkMode = 'dark';
401            } else if(self.darkMode == 'dark') {
402                if(autoAllowed == true) {
403                    self.darkMode = 'auto';
404                } else {
405                    self.darkMode = 'light';
406                }
407            } else if(self.darkMode == 'auto') {
408                self.darkMode = 'light';
409            } else {
410                self.darkMode = 'dark';
411            }
412
413            self.updateDarkMode();
414        });
415
416        this.updateDarkMode();
417    },
418
419    updateDarkMode: function () {
420        const html = document.querySelector('html');
421        let themeMode = this.darkMode;
422
423        if(this.darkMode == 'auto') {
424            html.dataset.themeAuto = true;
425
426            themeMode = 'light';
427            if (window.matchMedia) {
428                let prefersColorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
429                themeMode = prefersColorSchemeQuery.matches ? 'dark' : 'light';
430              }
431        } else {
432            delete html.dataset.themeAuto;
433        }
434
435        html.dataset.theme = `theme-${themeMode}`;
436        this.setCookie('lightDarkToggle', this.darkMode);
437    },
438
439    insertAfter: function (newNode, existingNode) {
440        existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
441    },
442
443    addToggleClick: function (elemToggle, elemCollapse) {
444        this.addEventListenerByClassName(elemToggle, 'click', function (event) {
445            event.preventDefault();
446            event.stopPropagation();
447            let nextSibling = mikio.getNextSibling(this, '.' + elemCollapse);
448
449            if (typeof nextSibling !== 'undefined') {
450                mikio.toggleCollapse(this, nextSibling);
451            }
452        });
453    },
454
455    addDropdownClick: function (elemToggle, elemCollapse) {
456        this.addEventListenerByClassName(elemToggle, 'click', function (event) {
457            event.preventDefault();
458            event.stopPropagation();
459
460            var dropdown = this.querySelector('.' + elemCollapse);
461            if (dropdown) {
462                mikio.toggleDropdown(dropdown);
463            }
464        });
465    },
466
467    addEventListenerByClassName: function (className, eventType, callback) {
468        Array.from(document.getElementsByClassName(className)).forEach(function (elem) {
469            elem.addEventListener(eventType, callback);
470        });
471    },
472
473    getNextSibling: function (elem, selector) {
474        var sibling = elem.nextElementSibling;
475
476        while (sibling) {
477            if (sibling.matches(selector)) return sibling;
478            sibling = sibling.nextElementSibling;
479        }
480    },
481
482    getPrevSibling: function (elem, selector) {
483        var sibling = elem.previousElementSibling;
484
485        while (sibling) {
486            if (sibling.matches(selector)) return sibling;
487            sibling = sibling.previousElementSibling;
488        }
489    },
490
491    toggleCollapse: function (objToggle, objCollapse) {
492        if (objToggle.classList.contains('closed')) {
493            objToggle.classList.remove('closed');
494            objToggle.classList.add('open');
495            var height = objCollapse.offsetHeight;
496            objCollapse.style.overflow = 'hidden';
497            objCollapse.style.height = 0;
498            objCollapse.style.paddingTop = 0;
499            objCollapse.style.paddingBottom = 0;
500            objCollapse.style.marginTop = 0;
501            objCollapse.style.marginBottom = 0;
502            objCollapse.offsetHeight;
503            objCollapse.style.boxSizing = 'border-box';
504            objCollapse.style.transitionProperty = "height, margin, padding";
505            objCollapse.style.transitionDuration = '500ms';
506            objCollapse.style.height = height + 'px';
507            objCollapse.style.removeProperty('padding-top');
508            objCollapse.style.removeProperty('padding-bottom');
509            objCollapse.style.removeProperty('margin-top');
510            objCollapse.style.removeProperty('margin-bottom');
511            window.setTimeout(function () {
512                objCollapse.style.removeProperty('height');
513                objCollapse.style.removeProperty('overflow');
514                objCollapse.style.removeProperty('transition-duration');
515                objCollapse.style.removeProperty('transition-property');
516                objCollapse.style.removeProperty('box-sizing');
517            }, 500);
518        } else {
519            objCollapse.style.transitionProperty = 'height, margin, padding';
520            objCollapse.style.transitionDuration = '500ms';
521            objCollapse.style.boxSizing = 'border-box';
522            objCollapse.style.height = objCollapse.offsetHeight + 'px';
523            objCollapse.offsetHeight;
524            objCollapse.style.overflow = 'hidden';
525            objCollapse.style.height = 0;
526            objCollapse.style.paddingTop = 0;
527            objCollapse.style.paddingBottom = 0;
528            objCollapse.style.marginTop = 0;
529            objCollapse.style.marginBottom = 0;
530            window.setTimeout(function () {
531                objToggle.classList.add('closed');
532                objToggle.classList.remove('open');
533                objCollapse.style.removeProperty('height');
534                objCollapse.style.removeProperty('padding-top');
535                objCollapse.style.removeProperty('padding-bottom');
536                objCollapse.style.removeProperty('margin-top');
537                objCollapse.style.removeProperty('margin-bottom');
538                objCollapse.style.removeProperty('overflow');
539                objCollapse.style.removeProperty('transition-duration');
540                objCollapse.style.removeProperty('transition-property');
541                objCollapse.style.removeProperty('box-sizing');
542            }, 500);
543        }
544    },
545
546
547    toggleDropdown: function (objToggle) {
548        if (objToggle.classList.contains('closed')) {
549            objToggle.classList.remove('closed');
550        } else {
551            objToggle.classList.add('closed');
552        }
553
554        Array.from(document.getElementsByClassName('mikio-dropdown')).forEach(function (elem) {
555            if (!elem.classList.contains('closed') && elem != objToggle) {
556                elem.classList.add('closed');
557            }
558        });
559    },
560
561    setHeroSubTitle: function (str) {
562        Array.from(document.getElementsByClassName('mikio-hero-subtitle')).forEach(function (elem) {
563            elem.innerHTML = str;
564        });
565    },
566
567    setHeroImage: function (str) {
568        var heroImages = document.getElementsByClassName('mikio-hero-image');
569
570        if (heroImages.length > 0) {
571            Array.from(document.getElementsByClassName('mikio-hero-image')).forEach(function (elem) {
572                elem.style.backgroundImage = 'url(\'' + str + '\')';
573                elem.classList.add('mikio-hero-image-resize');
574            });
575        } else {
576            Array.from(document.getElementsByClassName('mikio-hero-text')).forEach(function (elem) {
577                elem.insertAdjacentHTML('afterend', '<div class="mikio-hero-image mikio-hero-image-resize" style="background-image:url(\'' + str + '\');"></div>');
578            });
579        }
580    },
581
582    setHeroColor: function (str) {
583        var colors = str.trim().replace(/ +(?= )/g, '').split(/(?!\(.*)\s(?![^(]*?\))/g);
584        if (colors.length > 0 && colors[0] != '') {
585            Array.from(document.getElementsByClassName('mikio-hero')).forEach(function (elem) {
586                elem.style.backgroundColor = colors[0];
587            });
588
589            if (colors.length > 1) {
590                Array.from(document.getElementsByClassName('mikio-hero-title')).forEach(function (elem) {
591                    elem.style.color = colors[1];
592                });
593            }
594
595            if (colors.length > 2) {
596                Array.from(document.getElementsByClassName('mikio-hero-subtitle')).forEach(function (elem) {
597                    elem.style.color = colors[2];
598                });
599            }
600
601            if (colors.length > 3) {
602                Array.from(document.getElementsByClassName('mikio-hero')).forEach(function (parentElem) {
603                    Array.from(parentElem.querySelectorAll('.mikio-breadcrumbs ul li a')).forEach(function (elem) {
604                        elem.style.color = colors[3];
605                    });
606
607                    Array.from(parentElem.querySelectorAll('.mikio-breadcrumbs ul li, .mikio-breadcrumbs ul li a')).forEach(function (elem) {
608                        elem.style.color = colors[3];
609                        elem.onmouseover = function () { this.style.color = (colors.length > 4 ? colors[4] : 'initial'); };
610                        elem.onmouseout = function () { this.style.color = colors[3]; };
611                    });
612                });
613            }
614        }
615    },
616
617    setTags: function (str) {
618        Array.from(document.getElementsByClassName('mikio-tags')).forEach(function (elem) {
619            elem.innerHTML = str;
620        });
621    },
622
623    hidePart: function (part) {
624        var selectorArray = {
625            topheader: '.mikio-page-topheader',
626            header: '.mikio-page-header',
627            contentheader: '.mikio-page-contentheader',
628            contentfooter: '.mikio-page-contentfooter',
629            sidebarheader: '.mikio-sidebar-left .mikio-sidebar-header',
630            sidebarfooter: '.mikio-sidebar-left .mikio-sidebar-footer',
631            rightsidebarheader: '.mikio-sidebar-right .mikio-sidebar-header',
632            rightsidebarfooter: '.mikio-sidebar-right .mikio-sidebar-footer',
633            footer: '.mikio-footer',
634            bottomfooter: '.mikio-page-bottomfooter',
635            navbar: '.mikio-navbar',
636            hero: '.mikio-hero'
637        };
638
639        if (selectorArray.hasOwnProperty(part)) {
640            Array.from(document.querySelectorAll(selectorArray[part])).forEach(function (elem) {
641                elem.style.display = 'none';
642            });
643        }
644    },
645
646    indexmenuPatch: function () {
647        window.setTimeout(function () {
648            Array.from(document.querySelectorAll('a.navSel')).forEach(function (elem) {
649                let prev = mikio.getPrevSibling(elem, 'img');
650                if (prev) {
651                    prev.style.opacity = 1;
652                }
653            });
654        }, 50);
655
656
657        document.addEventListener('mouseover', function (event) {
658            const indexmenuClasses = ['nodeUrl', 'nodeSel', 'node'];
659            if ([...event.target.classList].some(className => indexmenuClasses.indexOf(className) !== -1)) {
660                let prev = mikio.getPrevSibling(event.target, 'img');
661                if (prev) {
662                    prev.style.opacity = 1;
663                }
664            }
665        });
666
667        document.addEventListener('mouseout', function (event) {
668            const indexmenuClasses = ['nodeUrl', 'nodeSel', 'node'];
669            if ([...event.target.classList].some(className => indexmenuClasses.indexOf(className) !== -1)) {
670                let prev = mikio.getPrevSibling(event.target, 'img');
671                if (prev) {
672                    prev.style.opacity = '';
673                }
674            }
675        });
676    },
677
678   // Add typeahead support for quick seach. Taken from bootstrap3 theme.
679    typeahead: function () {
680
681        jQuery(".search_typeahead").typeahead({
682
683            source: function (query, process) {
684
685                return jQuery.post(DOKU_BASE + 'lib/exe/ajax.php',
686                    {
687                        call: 'qsearch',
688                        q: encodeURI(query)
689                    },
690                    function (data) {
691
692                        var results = [];
693
694                        jQuery(data).find('a').each(function () {
695
696                            var page = jQuery(this);
697
698                            results.push({
699                                name: page.text(),
700                                href: page.attr('href'),
701                                title: page.attr('title'),
702                                category: page.attr('title').replace(/:/g, ' : '),
703                            });
704
705                        });
706
707                        return process(results);
708
709                    });
710            },
711
712            itemLink: function (item) {
713                return item.href;
714            },
715
716            itemTitle: function (item) {
717                return item.title;
718            },
719
720            followLinkOnSelect: true,
721            autoSelect: false,
722            items: 10,
723            fitToElement: true,
724            delay: 500,
725			theme: 'bootstrap4',
726
727        });
728    },
729
730    getCookie: function(cname) {
731        let name = cname + "=";
732        let decodedCookie = decodeURIComponent(document.cookie);
733        let ca = decodedCookie.split(';');
734        for (let i = 0; i < ca.length; i++) {
735            let c = ca[i];
736            while (c.charAt(0) == ' ') {
737                c = c.substring(1);
738            }
739            if (c.indexOf(name) == 0) {
740                return c.substring(name.length, c.length);
741            }
742        }
743        return "";
744    },
745
746    setCookie: function(cname, cvalue, exdays) {
747        const d = new Date();
748        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
749        let expires = "expires=" + d.toUTCString();
750        document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
751    },
752
753    clearCookie: function(cname) {
754        document.cookie = cname + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/";
755    },
756
757    colorToHex: function(color) {
758        // Create a canvas element
759        let canvas = document.createElement('canvas');
760        canvas.height = 1;
761        canvas.width = 1;
762        let ctx = canvas.getContext('2d');
763
764        // Set the fillStyle to the color input
765        ctx.fillStyle = color;
766        ctx.fillRect(0, 0, 1, 1);
767
768        // Get the pixel data from the canvas
769        let data = ctx.getImageData(0, 0, 1, 1).data;
770
771        // Convert the RGB values to HEX
772        let hex = '#' + ((1 << 24) + (data[0] << 16) + (data[1] << 8) + data[2]).toString(16).slice(1).toUpperCase();
773
774        return hex;
775    }
776};
777
778if (document.readyState != 'loading') {
779    mikio.ready();
780} else {
781    document.addEventListener('DOMContentLoaded', function () { mikio.ready() });
782}
783