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