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 // fade in the navigation (was hidden until now 149 $main.css({opacity: 0, visibility: "visible"}).animate({opacity: 1}, 200); 150 }, 151 152 /** 153 * Initialize the open/close toggling of menu entries 154 */ 155 initMenuHandling = function () { 156 $nav.on('click', 'div.nav a', function (e) { 157 toggleNav(jQuery(this)); 158 e.preventDefault(); 159 }); 160 }, 161 162 /** 163 * adds a given class to the toggler link 164 * @param $toggler link or parent of link to whom the class is added 165 * @param classVal class to be added 166 */ 167 setTogglerClass = function ($toggler, classVal) { 168 if($toggler.is('a')) { 169 $toggler.addClass(classVal); 170 } else { 171 $toggler.find('a').addClass(classVal); 172 } 173 }, 174 175 /** 176 * marks a $toggler link as active if the following menu has an active state 177 * @param $menuObj jQuery Object of the menu / container 178 * @param $toggler 179 */ 180 addContentMenuCurrentStates = function ($menuObj, $toggler) { 181 if($menuObj[0] && String($menuObj[0].innerHTML).indexOf('curid') > 0) { 182 setTogglerClass($toggler,'is-active'); 183 } 184 }, 185 186 /** 187 * Make sure the content area is always as high as the sidebar 188 */ 189 initContentMinHeight = function () { 190 var $sidebar = jQuery('.page-wrapper').find('> .tools').find('.col-xs-12'); 191 if ($sidebar.length == 1) { 192 var num = parseFloat($sidebar.height()); 193 if (!isNaN(num)) { 194 jQuery('#dokuwiki__content').css('minHeight', num + 100); 195 } 196 } 197 }, 198 199 /** 200 * Initialize the sidebar handle behaviour 201 */ 202 initSidebarToggling = function () { 203 var $toggler = jQuery('.togglelink.page_main-content').find('a'); 204 $toggler.click(function (e) { 205 e.preventDefault(); 206 if (jQuery('body').hasClass('wide-content')) { 207 setDefaultContent(); 208 } else { 209 setWideContent(); 210 removeOpenStates(); 211 } 212 }); 213 214 if (window.sessionStorage.getItem('wide-content') === 'true') { 215 setWideContent(); 216 } 217 }, 218 219 /** 220 * Show sidebar when accessing the search 221 */ 222 initSearchToggling = function () { 223 jQuery('.toggleSearch').find('a').click(function (e) { 224 setDefaultContent(); 225 e.preventDefault(); 226 jQuery('#qsearch__in').focus(); 227 }); 228 229 }, 230 231 /** 232 * Open and close the sidebar in mobile view 233 */ 234 initMobileToggling = function () { 235 jQuery('.menu-togglelink').find('a').click(function (e) { 236 e.preventDefault(); 237 var $body = jQuery('body'); 238 $body.toggleClass('show-mobile-sidebar'); 239 }); 240 }, 241 242 /** 243 * set is-active class if body has at least one of the given selectors 244 * @param selectorArray Array of selectors 245 * @param $nav container in which the $toggler is situated 246 */ 247 setActive = function(selectorArray, $nav) { 248 for(var i=0; i< selectorArray.length; i++) { 249 var mode = selectorArray[i]; 250 if(jQuery('body').is('.do-'+mode)){ 251 setTogglerClass($nav.find('.nav'),'is-active'); 252 $nav.find('a[href*="do='+mode+'"]').wrapAll('<span class="curid"></span>'); 253 } 254 } 255 }, 256 257 /** 258 * sets active states in site tool menu and user tool menu for certain modes 259 * adds sessionStorage behaviour equivalent approach to content menus 260 * 261 */ 262 initTemplateMenues = function () { 263 var $body = jQuery('body'), 264 $siteTools = $nav.find('> .nav-sitetools'), 265 $userTools = $nav.find('> .nav-usermenu'), 266 $templateMenus = $nav.find('> nav:not(.nav-main)'), 267 268 stModes = ['recent', 'media', 'index'], 269 utModes = ['profile','admin'], 270 isWideContent = false; 271 272 /* set active states for site tool menu and user tool menu */ 273 setActive(stModes,$siteTools); 274 setActive(utModes,$userTools); 275 276 if($body.is('.do-show') && $body.is('.wide-content')) { 277 window.sessionStorage.setItem('wide-content', true); 278 isWideContent = true; 279 } 280 281 282 283 /* set data attributes for sessionStorage and check onload if one of the template menus should be opened */ 284 $templateMenus.each(function( index ) { 285 var $t = jQuery(this).find('.nav'), 286 y = $nav.find('.nav-main').find('.nav').length, 287 $toggler = ($t.is('a')) ? $t : $t.find('a:last'), 288 tIndex = y + index; 289 $toggler.data('index', tIndex); 290 291 var item = window.sessionStorage.getItem('sidebar-section-' + tIndex + '-open'); 292 if (item) { 293 if(isWideContent) { 294 window.sessionStorage.setItem('sidebar-section-' + tIndex + '-open', 'false'); 295 } else { 296 if (item === 'true') { 297 jQuery(this).find('.nav-panel').css('display', 'block'); 298 setTogglerClass($toggler, 'is-open'); 299 } 300 } 301 } 302 //console.log(window.sessionStorage); 303 304 }); 305 306 }; 307 308 309 // main 310 initContentNav(); 311 initSidebarToggling(); 312 initTemplateMenues(); 313 initMenuHandling(); 314 initContentMinHeight(); 315 initSearchToggling(); 316 initMobileToggling(); 317}); 318 319