xref: /template/sprintdoc/js/sidebar.js (revision 13c822c242fe3e6b6b0178bf99029a650ef49d37)
1/**
2 * Sets up the sidebar behaviour
3 */
4jQuery(function () {
5    var $nav = jQuery('#dokuwiki__aside');
6    if (!$nav.length) return;
7
8        /**
9         * closes sidebar
10         */
11    var setWideContent = function () {
12            $nav.find('div.nav-panel').hide(); // close all panels
13            jQuery('body').addClass('wide-content');
14            removeToggleStorage();
15            window.sessionStorage.setItem('wide-content', true);
16        },
17
18        /**
19         * removes information about the toggle-state
20         */
21        removeToggleStorage = function () {
22            for (var index=0; index <= window.sessionStorage.length; index += 1) {
23                var item = window.sessionStorage.getItem('sidebar-section-' + index + '-open');
24                if (!item) {
25                    continue;
26                }
27                window.sessionStorage.removeItem('sidebar-section-' + index + '-open');
28            }
29        },
30
31        /**
32         * opens the sidebar
33         */
34        setDefaultContent = function () {
35            jQuery('body').removeClass('wide-content');
36            window.sessionStorage.setItem('wide-content', false);
37        },
38
39        /**
40         * Accessibility helper, focuses the first link witih the given element
41         *
42         * @param {jQuery} $elem
43         */
44        focusFirstSubLink = function ($elem) {
45            $elem.find('a').first().focus();
46        },
47
48        /**
49         * Toggle a navigation panel
50         *
51         * @param {jQuery} $toggler The a toggler
52         */
53         toggleNav = function ($toggler) {
54            var $panel = $toggler.parent().next('div.nav-panel');
55            var isOpen = $panel.is(':visible');
56            // open sidebar on interaction
57            setDefaultContent();
58            // toggle the panel, focus first link after opening
59            $panel.dw_toggle(!isOpen, function () {
60                if (!isOpen) {
61                    focusFirstSubLink($panel);
62                    $toggler.addClass('is-open');
63                } else {
64                    $toggler.removeClass('is-open');
65                }
66            });
67            window.sessionStorage.setItem('sidebar-section-' + $toggler.data('index') + '-open', !isOpen);
68        },
69
70        /**
71         * Initialize the content navigation
72         *
73         * It mangles the sidebar content and handles inline Icon configuration
74         */
75        initContentNav = function () {
76            var $main = $nav.find('nav.nav-main');
77            if (!$main.length) return;
78
79            if(jQuery('body').hasClass('wide-content')) {
80                removeToggleStorage();
81            }
82
83            var ELEMENT = JSINFO.template.sprintdoc.sidebar_toggle_elements;
84            var $elements = $main.find(ELEMENT);
85            $elements.each(function (index) {
86                var $me = jQuery(this),
87
88                // prepare text and the optional icon
89                    data = $me.text().split('@', 2),
90                    text = data[0].trim();
91
92                var $icon = jQuery('<span class="ico">')
93                    .text(text.substr(0, 1).toUpperCase() + text.substr(1, 1).toLowerCase())
94                    .wrapInner('<strong>');
95                if (data[1]) {
96                    var src = data[1].trim();
97                    $icon.load(DOKU_BASE + 'lib/tpl/sprintdoc/svg.php?svg=' + src + '&e=1'); // directly embed
98                }
99
100                // make the new toggler
101                var $toggler = jQuery('<a>')
102                        .attr('href', '#')
103                        .attr('role', 'heading')
104                        .attr('aria-level', '2')
105                        .text(text)
106                        .wrapInner('<span class="lbl">')
107                        .prepend($icon)
108                        .data('index', index)
109                    ;
110                $toggler = jQuery('<div class="nav">').prepend($toggler);
111
112
113                // wrap all following siblings til the next element in a wrapper
114                var $wrap = jQuery('<div>')
115                    .addClass('nav-panel');
116                var $sibs = $me.nextAll();
117
118                for (var i = 0; i < $sibs.length; i++) {
119                    var $sib = jQuery($sibs[i]);
120                    if ($sib.is(ELEMENT)) break;
121                    $sib.detach().appendTo($wrap);
122                    addContentMenuCurrentStates($sib, $toggler);
123                }
124                $wrap.insertAfter($me);
125
126                // replace element with toggler
127                $me.replaceWith($toggler);
128
129                if ($toggler.parent('li').length) {
130                    $toggler.parent('li').addClass('toggler');
131                }
132
133                if (window.sessionStorage.getItem('sidebar-section-' + index + '-open') === 'true') {
134                    $wrap.css('display', 'block');
135                    setTogglerClass($toggler,'is-open');
136                }
137
138            });
139        },
140
141        /**
142         * Initialize the open/close toggling of menu entries
143         */
144        initMenuHandling = function () {
145            $nav.on('click', 'div.nav a', function (e) {
146                toggleNav(jQuery(this));
147                e.preventDefault();
148            });
149        },
150
151        /**
152         * adds a given class to the toggler link
153         * @param $toggler link or parent of link to whom the class is added
154         * @param classVal class to be added
155         */
156        setTogglerClass = function ($toggler, classVal) {
157            if($toggler.is('a')) {
158                $toggler.addClass(classVal);
159            } else {
160                $toggler.find('a').addClass(classVal);
161            }
162        },
163
164        /**
165         * marks a $toggler link as active if the following menu has an active state
166         * @param $menuObj jQuery Object of the menu / container
167         * @param $toggler
168         */
169        addContentMenuCurrentStates = function ($menuObj, $toggler) {
170            if($menuObj[0] && String($menuObj[0].innerHTML).indexOf('curid') > 0) {
171                setTogglerClass($toggler,'is-active');
172            }
173        },
174
175        /**
176         * Make sure the content area is always as high as the sidebar
177         */
178        initContentMinHeight = function () {
179            var $sidebar = jQuery('.page-wrapper').find('> .tools').find('.col-xs-12');
180            if ($sidebar.length == 1) {
181                var num = parseFloat($sidebar.height());
182                if (!isNaN(num)) {
183                    jQuery('#dokuwiki__content').css('minHeight', num + 100);
184                }
185            }
186        },
187
188        /**
189         * Initialize the sidebar handle behaviour
190         */
191        initSidebarToggling = function () {
192            var $toggler = jQuery('.togglelink.page_main-content').find('a');
193            $toggler.click(function (e) {
194                e.preventDefault();
195                if (jQuery('body').hasClass('wide-content')) {
196                    setDefaultContent();
197                } else {
198                    setWideContent();
199                }
200            });
201
202            if (window.sessionStorage.getItem('wide-content') === 'true') {
203                setWideContent();
204            }
205        },
206
207        /**
208         * Show sidebar when accessing the search
209         */
210        initSearchToggling = function () {
211            jQuery('.toggleSearch').find('a').click(function (e) {
212                setDefaultContent();
213                e.preventDefault();
214                jQuery('#qsearch__in').focus();
215            });
216
217        },
218
219        /**
220         * Open and close the sidebar in mobile view
221         */
222        initMobileToggling = function () {
223            jQuery('.menu-togglelink').find('a').click(function (e) {
224                e.preventDefault();
225                var $body = jQuery('body');
226                $body.toggleClass('show-mobile-sidebar');
227            });
228        },
229
230        /**
231         * set is-active class if body has at least one of the given selectors
232         * @param selectorArray Array of selectors
233         * @param $nav container in which the $toggler is situated
234         */
235        setActive = function(selectorArray, $nav) {
236            for(var i=0; i< selectorArray.length; i++) {
237                var mode = selectorArray[i];
238                if(jQuery('body').is('.do-'+mode)){
239                    setTogglerClass($nav.find('.nav'),'is-active');
240                    $nav.find('a[href*="do='+mode+'"]').wrapAll('<span class="curid"></span>');
241                }
242            }
243        },
244
245        /**
246         * sets active states in site tool menu and user tool menu for certain modes
247         * adds sessionStorage behaviour equivalent approach to content menus
248         *
249         */
250        initTemplateMenues = function () {
251            var $body = jQuery('body'),
252                $siteTools = $nav.find('> .nav-sitetools'),
253                $userTools = $nav.find('> .nav-usermenu'),
254                $templateMenus = $nav.find('> nav:not(.nav-main)'),
255
256                stModes = ['recent', 'media', 'index'],
257                utModes = ['profile','admin'];
258
259            /* set active states for site tool menu and user tool menu */
260            setActive(stModes,$siteTools);
261            setActive(utModes,$userTools);
262
263            /* set data attributes for sessionStorage and check onload if one of the template menus should be opened */
264            $templateMenus.each(function( index ) {
265                var $t = jQuery(this).find('.nav'),
266                    y = $nav.find('.nav-main').find('.nav').length,
267                    $toggler = ($t.is('a')) ? $t : $t.find('a:last'),
268                    tIndex = y + index;
269                $toggler.data('index', tIndex);
270                if (window.sessionStorage.getItem('sidebar-section-' + tIndex + '-open') === 'true') {
271                    jQuery(this).find('.nav-panel').css('display', 'block');
272                    setTogglerClass($toggler,'is-open');
273                }
274            });
275
276        };
277
278    // main
279    initContentNav();
280    initSidebarToggling();
281    initTemplateMenues();
282    initMenuHandling();
283    initContentMinHeight();
284    initSearchToggling();
285    initMobileToggling();
286});
287
288