PageSourceSearch

https://www.malteser.de/_assets/56a966cb71f2557e1553752eadc05e45/JavaScript/jquery.accordion.js?1759194403

js malteser.de collected 2026-09-24 09:05:18 UTC 11,975 bytes, 373 lines download raw bytes

1/*!
2 * jQuery Accordion 0.0.1
3 * (c) 2014 Victor Fernandez <[email protected]>
4 * MIT Licensed.
5 *
6 * modified to set aria-hidden & aria-expanded on open/close for A11Y
7 * sets tabindex for <a> elements in the accordion content when opened or closed
8 */
9
10(function ($, window, document, undefined) {
11    var pluginName = "accordion",
12        defaults = {
13            transitionSpeed: 300,
14            transitionEasing: "ease",
15            controlElement: "[data-control]",
16            contentElement: "[data-content]",
17            groupElement: "[data-accordion-group]",
18            singleOpen: true,
19        };
20
21    function Accordion(element, options) {
22        this.element = element;
23        this.options = $.extend({}, defaults, options);
24        this._defaults = defaults;
25        this._name = pluginName;
26        this.init();
27    }
28
29    Accordion.prototype.init = function () {
30        var self = this,
31            opts = self.options;
32
33        var $accordion = $(self.element),
34            $controls = $accordion.find("> " + opts.controlElement),
35            $content = $accordion.find("> " + opts.contentElement);
36
37        var accordionParentsQty = $accordion.parents("[data-accordion]").length,
38            accordionHasParent = accordionParentsQty > 0;
39
40        var closedCSS = { "max-height": 0, overflow: "hidden" };
41
42        var CSStransitions = supportsTransitions();
43
44        function debounce(func, threshold, execAsap) {
45            var timeout;
46
47            return function debounced() {
48                var obj = this,
49                    args = arguments;
50
51                function delayed() {
52                    if (!execAsap) func.apply(obj, args);
53                    timeout = null;
54                }
55
56                if (timeout) clearTimeout(timeout);
57                else if (execAsap) func.apply(obj, args);
58
59                timeout = setTimeout(delayed, threshold || 100);
60            };
61        }
62
63        function supportsTransitions() {
64            var b = document.body || document.documentElement,
65                s = b.style,
66                p = "transition";
67
68            if (typeof s[p] == "string") {
69                return true;
70            }
71
72            var v = ["Moz", "webkit", "Webkit", "Khtml", "O", "ms"];
73
74            p = "Transition";
75
76            for (var i = 0; i < v.length; i++) {
77                if (typeof s[v[i] + p] == "string") {
78                    return true;
79                }
80            }
81
82            return false;
83        }
84
85        function requestAnimFrame(cb) {
86            if (
87                window.requestAnimationFrame ||
88                window.webkitRequestAnimationFrame ||
89                window.mozRequestAnimationFrame
90            ) {
91                return (
92                    requestAnimationFrame(cb) ||
93                    webkitRequestAnimationFrame(cb) ||
94                    mozRequestAnimationFrame(cb)
95                );
96            } else {
97                return setTimeout(cb, 1000 / 60);
98            }
99        }
100
101        function toggleTransition($el, remove) {
102            if (!remove) {
103                $content.css({
104                    "-webkit-transition":
105                        "max-height " +
106                        opts.transitionSpeed +
107                        "ms " +
108                        opts.transitionEasing,
109                    transition:
110                        "max-height " +
111                        opts.transitionSpeed +
112                        "ms " +
113                        opts.transitionEasing,
114                });
115            } else {
116                $content.css({
117                    "-webkit-transition": "",
118                    transition: "",
119                });
120            }
121        }
122
123        function calculateHeight($el) {
124            var height = 0;
125
126            $el.children().each(function () {
127                height = height + $(this).outerHeight(true);
128            });
129
130            $el.data("oHeight", height);
131        }
132
133        function updateParentHeight(
134            $parentAccordion,
135            $currentAccordion,
136            qty,
137            operation
138        ) {
139            var $content = $parentAccordion
140                    .filter(".accordion--open")
141                    .find("> [data-content]"),
142                $childs = $content.find(
143                    "[data-accordion].accordion--open > [data-content]"
144                ),
145                $matched;
146
147            if (!opts.singleOpen) {
148                $childs = $childs.not(
149                    $currentAccordion
150                        .siblings("[data-accordion].accordion--open")
151                        .find("> [data-content]")
152                );
153            }
154
155            $matched = $content.add($childs);
156
157            if ($parentAccordion.hasClass("accordion--open")) {
158                $matched.each(function () {
159                    var currentHeight = $(this).data("oHeight");
160
161                    switch (operation) {
162                        case "+":
163                            $(this).data("oHeight", currentHeight + qty);
164                            break;
165                        case "-":
166                            $(this).data("oHeight", currentHeight - qty);
167                            break;
168                        default:
169                            throw "updateParentHeight method needs an operation";
170                    }
171
172                    $(this).css("max-height", $(this).data("oHeight"));
173                });
174            }
175        }
176
177        function refreshHeight($accordion) {
178            if ($accordion.hasClass("accordion--open")) {
179                var $content = $accordion.find("> [data-content]"),
180                    $childs = $content.find(
181                        "[data-accordion].accordion--open > [data-content]"
182                    ),
183                    $matched = $content.add($childs);
184
185                calculateHeight($matched);
186
187                $matched.css("max-height", $matched.data("oHeight"));
188            }
189        }
190
191        function closeAccordion($accordion, $content) {
192            $accordion.trigger("accordion.close");
193            $content.attr('aria-hidden', true);
194            $controls.attr('aria-expanded', false);
195
196            $content.find("a").attr("tabindex", -1); // Set tabindex to -1
197
198            if (CSStransitions) {
199                if (accordionHasParent) {
200                    var $parentAccordions =
201                        $accordion.parents("[data-accordion]");
202
203                    updateParentHeight(
204                        $parentAccordions,
205                        $accordion,
206                        $content.data("oHeight"),
207                        "-"
208                    );
209                }
210
211                $content.css(closedCSS);
212
213                $accordion.removeClass("accordion--open");
214            } else {
215                $content.css("max-height", $content.data("oHeight"));
216
217                $content.animate(closedCSS, opts.transitionSpeed);
218
219                $accordion.removeClass("accordion--open");
220            }
221        }
222
223        function openAccordion($accordion, $content) {
224            $accordion.trigger("accordion.accordion--open");
225            $content.attr('aria-hidden', false);
226            $controls.attr('aria-expanded', true);
227
228            $content.find("a").attr("tabindex", 0); // Set tabindex to 0
229
230            if (CSStransitions) {
231                toggleTransition($content);
232
233                if (accordionHasParent) {
234                    var $parentAccordions =
235                        $accordion.parents("[data-accordion]");
236
237                    updateParentHeight(
238                        $parentAccordions,
239                        $accordion,
240                        $content.data("oHeight"),
241                        "+"
242                    );
243                }
244
245                requestAnimFrame(function () {
246                    $content.css("max-height", $content.data("oHeight"));
247                });
248
249                $accordion.addClass("accordion--open");
250            } else {
251                $content.animate(
252                    {
253                        "max-height": $content.data("oHeight"),
254                    },
255                    opts.transitionSpeed,
256                    function () {
257                        $content.css({ "max-height": "none" });
258                    }
259                );
260
261                $accordion.addClass("accordion--open");
262            }
263        }
264
265        function closeSiblingAccordions($accordion) {
266            var $accordionGroup = $accordion.closest(opts.groupElement);
267
268            var $siblings = $accordion
269                    .siblings("[data-accordion]")
270                    .filter(".accordion--open"),
271                $siblingsChildren = $siblings
272                    .find("[data-accordion]")
273                    .filter(".accordion--open");
274
275            var $otherAccordions = $siblings.add($siblingsChildren);
276
277            $otherAccordions.each(function () {
278                var $accordion = $(this),
279                    $content = $accordion.find(opts.contentElement);
280
281                closeAccordion($accordion, $content);
282            });
283
284            $otherAccordions.removeClass("accordion--open");
285        }
286
287        function toggleAccordion() {
288            var isAccordionGroup = opts.singleOpen
289                ? $accordion.parents(opts.groupElement).length > 0
290                : false;
291
292            calculateHeight($content);
293
294            if (isAccordionGroup) {
295                closeSiblingAccordions($accordion);
296            }
297
298            if ($accordion.hasClass("accordion--open")) {
299                closeAccordion($accordion, $content);
300            } else {
301                openAccordion($accordion, $content);
302            }
303            return false;
304        }
305
306        function addEventListeners() {
307            $controls.on("click", toggleAccordion);
308
309            $controls.on("accordion.toggle", function () {
310                if (opts.singleOpen && $controls.length > 1) {
311                    return false;
312                }
313
314                toggleAccordion();
315            });
316
317            $(window).on(
318                "resize",
319                debounce(function () {
320                    refreshHeight($accordion);
321                })
322            );
323        }
324
325        function setup() {
326            $content.each(function () {
327                var $curr = $(this);
328
329                if ($curr.css("max-height") != 0) {
330                    if (
331                        !$curr
332                            .closest("[data-accordion]")
333                            .hasClass("accordion--open")
334                    ) {
335                        $curr.css({ "max-height": 0, overflow: "hidden" });
336                        $curr.find("a").attr("tabindex", -1); // Set tabindex to -1 for closed accordions
337                    } else {
338                        toggleTransition($curr);
339                        calculateHeight($curr);
340
341                        $curr.css("max-height", $curr.data("oHeight"));
342                        $curr.find("a").attr("tabindex", 0); // Set tabindex to 0 for open accordions
343                    }
344                }
345            });
346
347            if (!$accordion.attr("data-accordion")) {
348                $accordion.attr("data-accordion", "");
349                $accordion.find(opts.controlElement).attr("data-control", "");
350                $accordion.find(opts.contentElement).attr("data-content", "");
351            }
352        }
353
354        setup();
355        addEventListeners();
356    };
357
358    $.fn[pluginName + "Class"] = function ($item) {
359        return new Accordion($item);
360    };
361
362    $.fn[pluginName] = function (options) {
363        return this.each(function () {
364            if (!$.data(this, "plugin_" + pluginName)) {
365                $.data(
366                    this,
367                    "plugin_" + pluginName,
368                    new Accordion(this, options)
369                );
370            }
371        });
372    };
373})(jQuery, window, document);

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.