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