xref: /template/sprintdoc/js/sidebar.js (revision a36c5fa052075746db9f0a937728a8df6c2c9079)
1/**
2 * Sets up the sidebar behaviour
3 */
4jQuery(function () {
5    const $nav = jQuery('#dokuwiki__aside');
6    if (!$nav.length) return;
7
8    /**
9     * closes sidebar
10     */
11    const setWideContent = function () {
12        $nav.find('div.nav-panel').hide(); // close all panels
13        jQuery('body').addClass('wide-content');
14    };
15
16    /**
17     * opens the sidebar
18     */
19    const setDefaultContent = function () {
20        jQuery('body').removeClass('wide-content');
21
22    };
23
24    /**
25     * Accessibility helper, focuses the first link witih the given element
26     *
27     * @param {jQuery} $elem
28     */
29    const focusFirstSubLink = function ($elem) {
30        $elem.find('a').first().focus();
31    };
32
33    /**
34     * Toggle a navigation panel
35     *
36     * @param {jQuery} $toggler The h6 toggler
37     */
38    const toggleNav = function ($toggler) {
39        const $panel = $toggler.next('div.nav-panel');
40        const isOpen = $panel.is(':visible');
41        // open sidebar on interaction
42        setDefaultContent();
43        // toggle the panel, focus first link after opening
44        $panel.dw_toggle(!isOpen, function () {
45            if (!isOpen) {
46                focusFirstSubLink($panel);
47            }
48        });
49    };
50
51    /**
52     * Initialize the content navigation
53     *
54     * It mangles the sidebar content and handles inline Icon configuration
55     */
56    const initContentNav = function () {
57        const $main = $nav.find('nav.nav-main');
58        if (!$main.length) return;
59
60        const ELEMENT = 'h1,h2,h3,h4,h5'; // FIXME move to config
61        const $elements = $main.find(ELEMENT);
62        $elements.each(function () {
63            const $me = jQuery(this);
64
65            // prepare text and the optional icon
66            const data = $me.text().split('@', 2);
67            const text = data[0].trim();
68            const $icon = jQuery('<span class="ico">')
69                .text(text.substr(0, 1).toUpperCase() + text.substr(1, 1).toLowerCase())
70                .wrapInner('<strong>');
71            if (data[1]) {
72                const src = data[1].trim();
73                $icon.load(DOKU_BASE + 'lib/tpl/sprintdoc/svg.php?svg=' + src + '&e=1'); // directly embed
74            }
75
76            // make the new toggler
77            const $toggler = jQuery('<h6>')
78                    .attr('role', 'heading')
79                    .attr('aria-level', '2')
80                    .text(text)
81                    .wrapInner('<span class="lbl">')
82                    .prepend($icon)
83                ;
84
85            // wrap all following siblings til the next element in a wrapper
86            const $wrap = jQuery('<div>')
87                .addClass('nav-panel');
88            const $sibs = $me.nextAll();
89            for (let i = 0; i < $sibs.length; i++) {
90                const $sib = jQuery($sibs[i]);
91                if ($sib.is(ELEMENT)) break;
92                $sib.detach().appendTo($wrap);
93            }
94            $wrap.insertAfter($me);
95
96            // replace element with toggler
97            $me.replaceWith($toggler);
98        });
99    };
100
101    /**
102     * Initialize the open/close toggling of menu entries
103     */
104    const initMenuHandling = function () {
105        $nav.on('click', 'h6', function () {
106            toggleNav(jQuery(this));
107        });
108    };
109
110    /**
111     * Make sure the content area is always as high as the sidebar
112     */
113    const initContentMinHeight = function () {
114        const $sidebar = jQuery('.page-wrapper').find('> .tools').find('.col-xs-12');
115        if ($sidebar.length == 1) {
116            const num = parseFloat($sidebar.height());
117            if (!isNaN(num)) {
118                jQuery('#dokuwiki__content').css('minHeight', num + 100);
119            }
120        }
121    };
122
123    /**
124     * Initialize the sidebar handle behaviour
125     */
126    const initSidebarToggling = function () {
127        const $toggler = jQuery('.togglelink.page_main-content').find('a');
128        $toggler.click(function (e) {
129            e.preventDefault();
130            if (jQuery('body').hasClass('wide-content')) {
131                setDefaultContent();
132            } else {
133                setWideContent();
134            }
135        });
136    };
137
138    /**
139     * Show sidebar when accessing the search
140     */
141    const initSearchToggling = function () {
142        jQuery('.toggleSearch').find('a').click(function (e) {
143            setDefaultContent();
144            e.preventDefault();
145            jQuery('#qsearch__in').focus();
146        });
147
148    };
149
150    // main
151    initContentNav();
152    initSidebarToggling();
153    initMenuHandling();
154    initContentMinHeight();
155    initSearchToggling();
156});
157
158