1;(function ($) { 2 3 var prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; 4 5 var defaults = { 6 hashEvents : 'load hashchange', 7 8 titleSelector : '.accordion-title', 9 containerSelector : '.accordion-container', 10 11 iconStyle : 'fal', 12 iconOpen : 'fa-plus', 13 iconClose : 'fa-minus', 14 15 autoOpenFirst : false, 16 autoClose : false, 17 18 wrapInner : true, 19 activeCls : 'active', 20 useAnimations : false 21 }; 22 23 var Plugin = function(rootNode, options) { 24 var me = this, 25 op = $.extend({}, options || {}); 26 27 //Optionen aus den Data-Attributen zuweisen 28 $.each($(rootNode).data(), function(key, value) { 29 $.map(defaults, function(defValue, defKey) { 30 if (defKey.toLowerCase() == key.toLowerCase()) { 31 op[defKey] = value; 32 } 33 }); 34 }); 35 36 $.extend(me, { 37 rootNode : rootNode, 38 options : $.extend({}, defaults, op) 39 }); 40 41 me.init(); 42 }; 43 44 Plugin.prototype = { 45 46 init: function() { 47 var me = this, 48 op = me.options; 49 50 window.globalIkissAccordionCounter = (window.globalIkissAccordionCounter || 0)+1; 51 52 //Ueberschriften suchen und Elemente entsprechend modifizieren (bei dem neuen Accordion nur direkte Titel sammeln, daher Selektor mit > erweitern) 53 if (me.rootNode == document.body) { 54 me.header = $(op.titleSelector, me.rootNode); 55 } else { 56 me.header = $('> '+op.titleSelector, me.rootNode); 57 if (!me.header.length) me.header = $('> div > '+op.titleSelector, me.rootNode); 58 } 59 60 61 me.header.each(function(idx, node) { 62 var idKey = '-'+window.globalIkissAccordionCounter+'-'+(idx+1), 63 ctSel = op.containerSelector; 64 65 if (op.wrapInner) { 66 $(node) 67 .wrapInner('<button id="acc'+idKey+'" aria-controls="sect'+idKey+'" aria-expanded="false" type="button"><span></span><i class="accordion-toggle-button '+op.iconStyle+' '+op.iconOpen+'" aria-hidden="true"></i></button>'); 68 } else { 69 $(node) 70 .attr({'id': 'acc'+idKey, 'aria-controls': 'sect'+idKey, 'aria-expanded': 'false', 'tabindex': '0'}) 71 .keypress(function(evt) { if (evt.which === 13) { me.onClick.apply(me, arguments); } }); 72 } 73 74 window.photoswipeAccCounter = window.photoswipeAccCounter || 1; 75 76 $(node) 77 .click(function() { me.onClick.apply(me, arguments); }) 78 .next(ctSel) 79 .attr({'id': 'sect'+idKey, 'aria-labelledby': 'acc'+idKey, 'role': 'region'}) 80 .css('display', 'none') 81 .find('.photoswipe-gallery') 82 .filter(function() { return $(this).closest(ctSel).get(0) == $(node).next(ctSel).get(0); }) 83 .attr('data-photoswipe-group', 'acc-'+(window.photoswipeAccCounter++)); 84 }); 85 86 //Beim Fokus mittels TabKey CSS-Klasse setzen 87 me.header.on('focusin', function(e){ 88 var me = this; 89 $(window).one('keyup.tabkey', function (e) { 90 if ((e.keyCode ? e.keyCode : e.which) == 9) { 91 $(me).addClass('accordion-tab-focus'); 92 } 93 }); 94 }).on('focusout', function(e){ 95 $(this).removeClass('accordion-tab-focus'); 96 $(window).off('keyup.tabkey'); 97 }); 98 99 100 //Erstes Element öffnen? 101 if (op.autoOpenFirst && me.header.length) { 102 me.toggle(me.header[0]); 103 } 104 105 //Events bei denen der location.hash geprüft werden soll 106 $(window).on(op.hashEvents, function(){ me.checkHash.apply(me, arguments);}); 107 108 //ab jQuery 3.x wird das load event in docready manchmal nicht mehr ausgeführt, daher manueller Aufruf 109 if (document.readyState === 'complete') { 110 me.checkHash(); 111 } 112 }, 113 114 onClick: function(e) { 115 var me = this, 116 op = me.options; 117 118 var trgHeader = $(e.target).closest(op.titleSelector).get(0); 119 120 if (!trgHeader) 121 return; 122 123 e.preventDefault(); 124 e.stopPropagation(); 125 126 this.toggle(trgHeader); 127 }, 128 129 open: function(header) { 130 this.toggle(header, 'open'); 131 }, 132 133 close: function(header) { 134 this.toggle(header, 'close'); 135 }, 136 137 toggle: function(header, forceMode) { 138 var me = this, 139 op = me.options, 140 io = op.iconOpen, 141 ic = op.iconClose, 142 mode = $(header).hasClass(op.activeCls) ? 'close' : 'open', 143 open = (mode == 'open' || forceMode == 'open'); 144 145 if (open && op.autoClose) { 146 var acHeader = (me.rootNode == document.body)
147 ? $(op.titleSelector+'.'+op.activeCls, ($(header).closest(op.containerSelector).get(0) || document.body)).get(0) 148 : (me.header.filter('.'+op.activeCls)).get(0); 149 150 if (acHeader && acHeader != header) { 151 this.close(acHeader); 152 153 var offTop = parseInt($(header).offset().top, 10), 154 scTop = parseInt($(header).css('scroll-margin-top'), 10); 155 if (scTop) { 156 offTop -= scTop; 157 } 158 159 if (offTop < $(window).scrollTop()) { 160 if (prefersReducedMotion) { 161 $('html, body').scrollTop(offTop); 162 } else { 163 $('html, body').animate({scrollTop: offTop}, 500); 164 } 165 } 166 } 167 } 168 169 $(header).toggleClass(op.activeCls); 170 171 var $container = $(header).next(op.containerSelector); 172 if (op.useAnimations === true && !prefersReducedMotion) { 173 $container[open ? 'slideDown' : 'slideUp'](); 174 } else { 175 $container.css('display', open ? '' : 'none'); 176 } 177 178 if ($('button', header).length) { 179 $('button', header).attr('aria-expanded', open ? 'true': 'false'); 180 } else { 181 $(header).attr('aria-expanded', open ? 'true': 'false'); 182 } 183 184 $('i'+(op.wrapInner ? '.accordion-toggle-button' : ''), header).removeClass(open ? io : ic).addClass(open ? ic : io); 185 }, 186 187 checkHash: function() { 188 var me = this, 189 op = me.options, 190 hash = decodeURI(window.location.hash || ''), 191 hashID = hash && hash.substr(1), 192 trgEl; 193 194 if (hashID) { 195 var els = me.rootNode.getElementsByTagName("*"); 196 for (var i=0, len = els.length; i < len; i++) { 197 if (els[i].getAttribute('id') == hashID || els[i].getAttribute('data-anchor') == hashID) { 198 trgEl = els[i]; 199 break; 200 } 201 } 202 } 203 204 if (!trgEl || $(trgEl).hasClass(op.activeCls)) 205 return; 206 207 var ctSelector = op.containerSelector, 208 tiSelector = op.titleSelector, 209 openHit = 0; 210 211 if (me.rootNode == document.body) { 212 $(trgEl).parentsUntil(me.rootNode, ctSelector).each(function(idx, ct) { 213 me.open($(ct).prev(tiSelector).get(0)); 214 openHit = 1; 215 }); 216 } else { 217 var ct = $(trgEl).parentsUntil(me.rootNode, ctSelector).last(), 218 hd = ct.length ? 0 : $(trgEl).closest(tiSelector).get(0); 219 220 openHit = 1; 221 222 me.open(hd ? hd : $(ct).prev(tiSelector).get(0)); 223 } 224 225 if (openHit) { 226 var topPos = parseInt($(trgEl).offset().top, 10), 227 scTop = parseInt($(trgEl).css('scroll-margin-top'), 10) || parseInt($('> button', trgEl).css('scroll-margin-top'), 10); 228 229 if (topPos < 10 || window.globalIkissAccordionIsScrolling === true) 230 return; 231 232 if (scTop) { 233 topPos -= scTop; 234 } 235 236 window.globalIkissAccordionIsScrolling = true; 237 238 if (prefersReducedMotion) { 239 $('html, body').scrollTop(topPos); 240 window.globalIkissAccordionIsScrolling = false; 241 } else { 242 $('html, body').animate({scrollTop: topPos}, 500); 243 } 244 245 } 246 } 247 248 }; 249 250 $.fn.ikissAccordion = function (options) { 251 var pKey = (options && options.pluginKey) || 'ikissAccordion'; 252 return this.each(function() { 253 if (!$.data(this, pKey)) { 254 $.data(this, pKey, new Plugin(this, options)); 255 } 256 }); 257 }; 258 259 //Kompatibilität zur alten Accordion Syntax 260 window.ikissAccordion = function(config) { 261 262 var cf = $.extend({ 263 titleSelector : '.toggler-title', 264 containerSelector : '.toggler-container', 265 openFirstOnLoad : false, 266 wrapInner : false 267 }, config || {}); 268 269 $.extend(cf, { 270 pluginKey : (cf.titleSelector+'-'+cf.containerSelector).replace(/\./g, ''), 271 autoOpenFirst : (cf.openFirstOnLoad || cf.autoOpenFirst) 272 }); 273 delete cf.openFirstOnLoad; 274 275 $(document.body).ikissAccordion(cf); 276 }; 277 278})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.