PageSourceSearch

https://energyexperts.ai/wp-content/plugins/energyExperts/assets/js/ee-portal-nav.js?ver=2.25.616

js energyexperts.ai collected 2026-10-05 12:12:04 UTC 6,582 bytes, 192 lines download raw bytes

1/**
2 * EnergyExperts Portal — Sidebar-Steuerung
3 *
4 * Zwei getrennte Zustaende, beide als Klasse auf <html>:
5 *   ee-portal-collapsed   Desktop: Sidebar schmal (nur Kurzzeichen).
6 *   ee-portal-mobile-open Mobil:   Off-canvas-Sidebar sichtbar.
7 *
8 * Der Desktop-Zustand wird in localStorage gehalten und GANZ OBEN — noch
9 * waehrend des <head>-Parsings, bevor der Body gezeichnet wird — angewandt.
10 * Deshalb wird dieses Script ohne defer im Head geladen: sonst blitzt bei
11 * jedem Seitenwechsel kurz das volle Menue auf.
12 *
13 * Zusaetzlich merkt sich das Script den zuletzt besuchten Bereich und loest
14 * damit den Einstieg ueber die Portal-Wurzel /portal auf (siehe unten).
15 *
16 * Vanilla-JS, kein Framework, keine globalen Namen ausser dem IIFE.
17 */
18(function () {
19    'use strict';
20
21    var STORAGE_KEY = 'eePortalSidebarCollapsed';
22    var LAST_AREA_KEY = 'eePortalLastArea';
23    var CLASS_COLLAPSED = 'ee-portal-collapsed';
24    var CLASS_MOBILE_OPEN = 'ee-portal-mobile-open';
25    var MOBILE_BREAKPOINT = 768;
26
27    var root = document.documentElement;
28
29    /**
30     * localStorage kann in Privat-Modi werfen — jeder Zugriff ist gekapselt,
31     * der Toggle funktioniert dann eben ohne Persistenz statt gar nicht.
32     */
33    function readStored(key) {
34        try {
35            return window.localStorage.getItem(key);
36        } catch (e) {
37            return null;
38        }
39    }
40
41    function writeStored(key, value) {
42        try {
43            window.localStorage.setItem(key, value);
44        } catch (e) {
45            /* kein Speicher verfuegbar — Zustand gilt nur fuer diese Seite */
46        }
47    }
48
49    function clearStored(key) {
50        try {
51            window.localStorage.removeItem(key);
52        } catch (e) {
53            /* nichts zu tun */
54        }
55    }
56
57    // ------------------------------------------------------------------
58    // Einstieg ueber die Portal-Wurzel /portal
59    //
60    // Der Server kennt den zuletzt besuchten Bereich nicht (er steht nur im
61    // localStorage), liefert aber am <html>-Element die Entscheidungsgrundlage:
62    // erlaubte Bereiche, Basis-URL und Rueckfall-Ziel. Weil dieses Script ohne
63    // defer im Head laeuft, ist das <html>-Tag bereits geparst — die Adresse
64    // wird ersetzt, bevor irgendetwas gezeichnet wird. Ist der gemerkte Bereich
65    // fuer die Rolle nicht (mehr) erlaubt, greift der Rueckfall.
66    // ------------------------------------------------------------------
67    if (root.getAttribute('data-ee-portal-entry')) {
68        (function () {
69            var base = root.getAttribute('data-ee-portal-base') || '';
70            var fallback = root.getAttribute('data-ee-portal-fallback') || '';
71            var allowed = (root.getAttribute('data-ee-portal-areas') || '').split(',');
72            var last = readStored(LAST_AREA_KEY);
73            var target = '';
74
75            if (last && base && allowed.indexOf(last) !== -1) {
76                target = base + last + '/';
77            } else if (fallback) {
78                target = fallback;
79            }
80
81            if (target) {
82                window.location.replace(target);
83            }
84        })();
85
86        return;
87    }
88
89    // ------------------------------------------------------------------
90    // Letzten Bereich merken
91    //
92    // Nur erreichbare Bereiche werden gemerkt. Wird ein Bereich verweigert
93    // (403-Panel), fliegt genau dieser Eintrag raus, damit die Wurzel nicht
94    // dauerhaft in eine gesperrte Ansicht zeigt.
95    // ------------------------------------------------------------------
96    (function () {
97        var area = root.getAttribute('data-ee-portal-area');
98
99        if (!area) {
100            return;
101        }
102
103        if (root.getAttribute('data-ee-portal-denied')) {
104            if (readStored(LAST_AREA_KEY) === area) {
105                clearStored(LAST_AREA_KEY);
106            }
107            return;
108        }
109
110        writeStored(LAST_AREA_KEY, area);
111    })();
112
113    function isCollapsed() {
114        return root.classList.contains(CLASS_COLLAPSED);
115    }
116
117    function isMobile() {
118        return window.matchMedia
119            ? window.matchMedia('(max-width: ' + MOBILE_BREAKPOINT + 'px)').matches
120            : window.innerWidth <= MOBILE_BREAKPOINT;
121    }
122
123    // --- Schritt 1: gespeicherten Zustand sofort anwenden (kein Flackern) ---
124    if (readStored(STORAGE_KEY) === '1') {
125        root.classList.add(CLASS_COLLAPSED);
126    }
127
128    // --- Schritt 2: Bedienelemente verdrahten, sobald das DOM steht ---
129    function syncAria(collapseBtn, burgerBtn) {
130        if (collapseBtn) {
131            collapseBtn.setAttribute('aria-expanded', isCollapsed() ? 'false' : 'true');
132        }
133        if (burgerBtn) {
134            burgerBtn.setAttribute(
135                'aria-expanded',
136                root.classList.contains(CLASS_MOBILE_OPEN) ? 'true' : 'false'
137            );
138        }
139    }
140
141    function init() {
142        var collapseBtn = document.querySelector('[data-ee-portal-collapse]');
143        var burgerBtn = document.querySelector('[data-ee-portal-burger]');
144        var scrim = document.querySelector('[data-ee-portal-close]');
145
146        function closeMobile() {
147            root.classList.remove(CLASS_MOBILE_OPEN);
148            syncAria(collapseBtn, burgerBtn);
149        }
150
151        if (collapseBtn) {
152            collapseBtn.addEventListener('click', function () {
153                // Auf schmalen Viewports ist die Sidebar off-canvas; der
154                // Collapse-Knopf schliesst sie dort, statt sie zu verschmaelern.
155                if (isMobile()) {
156                    closeMobile();
157                    return;
158                }
159
160                var next = !isCollapsed();
161                root.classList.toggle(CLASS_COLLAPSED, next);
162                writeStored(STORAGE_KEY, next ? '1' : '0');
163                syncAria(collapseBtn, burgerBtn);
164            });
165        }
166
167        if (burgerBtn) {
168            burgerBtn.addEventListener('click', function () {
169                root.classList.toggle(CLASS_MOBILE_OPEN);
170                syncAria(collapseBtn, burgerBtn);
171            });
172        }
173
174        if (scrim) {
175            scrim.addEventListener('click', closeMobile);
176        }
177
178        document.addEventListener('keydown', function (event) {
179            if (event.key === 'Escape' && root.classList.contains(CLASS_MOBILE_OPEN)) {
180                closeMobile();
181            }
182        });
183
184        syncAria(collapseBtn, burgerBtn);
185    }
186
187    if (document.readyState === 'loading') {
188        document.addEventListener('DOMContentLoaded', init);
189    } else {
190        init();
191    }
192})();

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.