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