PageSourceSearch

https://www.bankmillennium.pl/dist/assets/scHeader/mobile-nav-generator.js?ts=20260921233541

js bankmillennium.pl collected 2026-09-24 09:44:29 UTC 17,252 bytes, 410 lines download raw bytes

1(function (businessLine, navbar, buttons) {
2    function toggleFocusable(container, enable) {
3        const focusableSelectors = [
4            'a[href]',
5            'button',
6            'input',
7            'select',
8            'textarea',
9            '[tabindex]',
10        ];
11
12        const elements = container.querySelectorAll(focusableSelectors.join(','));
13
14        elements.forEach((el) => {
15            const elementClassess = el.parentNode.classList;
16            const isMobileNavigationBusinessLineElement =
17                elementClassess.contains('business-line--elem');
18            const isMobileNavigationBusinessLineActiveElement =
19                isMobileNavigationBusinessLineElement && elementClassess.contains('active');
20
21            if (
22                enable &&
23                (!isMobileNavigationBusinessLineElement ||
24                    isMobileNavigationBusinessLineActiveElement)
25            ) {
26                if (el.dataset.prevTabindex !== undefined) {
27                    el.setAttribute('tabindex', el.dataset.prevTabindex);
28                    delete el.dataset.prevTabindex;
29                } else {
30                    el.removeAttribute('tabindex');
31                }
32            } else {
33                if (el.hasAttribute('tabindex')) {
34                    el.dataset.prevTabindex = el.getAttribute('tabindex');
35                }
36                el.setAttribute('tabindex', '-1');
37            }
38        });
39    }
40    function createFocusTrap(containerSelector) {
41        const container = document.querySelector(containerSelector);
42        if (!container) return;
43
44        const focusableSelectors = [
45            'a[href]',
46            'button:not([disabled])',
47            'input:not([disabled]):not([type="hidden"])',
48            'select:not([disabled])',
49            'textarea:not([disabled])',
50            '[tabindex]:not([tabindex="-1"])',
51        ];
52
53        let focusableElements = [];
54        let firstElement;
55        let lastElement;
56
57        function updateFocusableElements() {
58            focusableElements = container.querySelectorAll(focusableSelectors.join(','));
59            firstElement = focusableElements[0];
60            lastElement = focusableElements[focusableElements.length - 1];
61        }
62
63        function interceptOutsideFocus(e) {
64            if (e.key === 'Tab') {
65                const active = document.activeElement;
66                const isInsideTrap = container.contains(active);
67
68                if (!isInsideTrap) {
69                    e.preventDefault();
70                    firstElement.focus();
71                }
72            }
73        }
74
75        function handleKeyDown(e) {
76            if (e.key === 'Tab') {
77                if (e.shiftKey) {
78                    if (document.activeElement === firstElement) {
79                        e.preventDefault();
80                        lastElement.focus();
81                    }
82                } else if (document.activeElement === lastElement) {
83                    e.preventDefault();
84                    firstElement.focus();
85                }
86            }
87        }
88
89        return {
90            activate() {
91                updateFocusableElements();
92                container.addEventListener('keydown', handleKeyDown);
93                document.addEventListener('keydown', interceptOutsideFocus);
94            },
95            deactivate() {
96                container.removeEventListener('keydown', handleKeyDown);
97                document.removeEventListener('keydown', interceptOutsideFocus);
98            },
99        };
100    }
101
102    const mobileMenuFocusTrap = createFocusTrap('.sc-mobile-nav');
103
104    let _businessLine = document.querySelector(businessLine);
105    let isAfterModifications = false;
106    if (_businessLine.tagName !== 'UL') {
107        _businessLine = _businessLine.querySelector('ul');
108        isAfterModifications = true;
109    }
110    const _navbar = document.querySelector(navbar);
111    const _buttons = document.querySelector(buttons);
112    const _this =
113        document.querySelector('#mobile-navigation') || document.querySelector('nav.mobile');
114    if (!_businessLine || !_navbar || !_buttons) {
115        console.warn('no ', businessLine, ' or ', navbar, ' or ', _buttons, 'element found');
116        return false;
117    }
118    const _buttonsNavCon = _this.querySelector('.buttons');
119    let _bm = document.querySelector('#bm');
120    if (document.querySelector('link[href*=style-px]') === null) {
121        _bm = document.querySelector('body');
122    }
123
124    _this.appendChild(_buttonsNavCon);
125
126    if (_this) {
127        const _businessLineList = _this.querySelectorAll('.business-line');
128        if (_businessLineList[0].childNodes.length > 0) {
129            _businessLineList[0].innerHTML = '';
130            _businessLineList[1].innerHTML = '';
131        }
132        let _activeNode = Array.from(_businessLine.children)
133            .map((elem) => {
134                const newNode = elem.cloneNode(true);
135                _businessLineList[0].appendChild(newNode);
136
137                let _href = newNode.querySelector('a').getAttribute('href');
138                if (_href.indexOf('menu=open') === -1) {
139                    if (_href.indexOf('#') === -1) _href += '?menu=open';
140                    else {
141                        _href = _href.split('#');
142                        if (_href[0].indexOf('?') === -1) {
143                            _href = `${_href[0]}?menu=open#${_href[1]}`;
144                        } else {
145                            _href = `${_href[0]}&menu=open#${_href[1]}`;
146                        }
147                    }
148                }
149                newNode.querySelector('a').setAttribute('href', _href);
150                newNode.classList.add('business-line--elem');
151                if (newNode && !newNode.classList.contains('active')) {
152                    newNode.querySelector('a').setAttribute('tabindex', '-1');
153                }
154                return newNode;
155            })
156            .filter((item) => item.classList.contains('active'));
157
158        if (_activeNode.length === 0) {
159            const _about = _businessLineList[0].children[0].cloneNode(true);
160            _about.classList.add('active');
161            const aboutLink = _about.querySelector('a');
162            if (document.firstElementChild.getAttribute('lang').indexOf('pl') !== -1) {
163                aboutLink.innerHTML = 'O banku';
164                aboutLink.setAttribute('href', '/o-banku?menu=open');
165            } else {
166                aboutLink.innerHTML = 'About the Bank';
167                aboutLink.setAttribute('href', '/en/about-the-bank');
168            }
169            _businessLineList[0].appendChild(_about);
170            _activeNode = [_about];
171        }
172
173        _businessLineList[0].dataset.height =
174            72 + 20 + 52 * (_businessLineList[0].childNodes.length - 1);
175        if (parseInt(_businessLineList[0].dataset.height, 10) < 250)
176            _businessLineList[0].dataset.height = 300;
177        _businessLineList[0].classList.add('business-line--close');
178        _businessLineList[1].classList.add('business-line--secondary');
179
180        if (_businessLineList[0].firstElementChild.classList.contains('active') === false)
181            _businessLineList[0].insertBefore(_activeNode[0], _businessLineList[0].firstChild);
182        Array.from(_navbar.firstElementChild.children).map((elem) => {
183            const newNode = elem.cloneNode(true);
184            const _icon = document.createElement('i');
185            _icon.className = 'icon--f-arrow';
186            _icon.setAttribute('aria-hidden', 'true');
187            newNode.appendChild(_icon);
188            _businessLineList[1].appendChild(newNode);
189            return newNode;
190        });
191
192        _activeNode[0].addEventListener('click', (event) => {
193            event.preventDefault();
194            const _heightOnOpen =
195                _bm.dataset.heightCup * 1 + _businessLineList[0].dataset.heightCup * 1;
196            if (_businessLineList[0].style.length > 0) {
197                _businessLineList[0].style.maxHeight = null;
198                _businessLineList[0].classList.add('business-line--close');
199
200                _bm.classList.remove(`height-constraint-for-modal--${_heightOnOpen}`);
201                _bm.classList.add(`height-constraint-for-modal--${_bm.dataset.heightCup}`);
202
203                _businessLineList[0].querySelectorAll('.business-line--elem a').forEach((elem) => {
204                    if (!elem.parentElement.classList.contains('active')) {
205                        elem.setAttribute('tabindex', '-1');
206                    }
207                });
208            } else {
209                _businessLineList[0].style.maxHeight = `${_businessLineList[0].dataset.height}px`;
210                _businessLineList[0].classList.remove('business-line--close');
211
212                _bm.classList.add(`height-constraint-for-modal--${_heightOnOpen}`);
213                _bm.classList.remove(`height-constraint-for-modal--${_bm.dataset.height
213Cup}`);
214                _businessLineList[0].querySelectorAll('.business-line--elem a').forEach((elem) => {
215                    elem.setAttribute('tabindex', '0');
216                });
217            }
218        });
219
220        _businessLineList[1].dataset.height = Math.ceil(_businessLineList[1].offsetHeight / 10);
221
222        const _i = document.createElement('i');
223        _i.className = 'icon--f-arrow';
224        _i.setAttribute('aria-hidden', 'true');
225        _activeNode[0].querySelector('a').appendChild(_i);
226
227        const _menuBefore = document.createElement('div');
228        _menuBefore.className = 'sc-mobile-nav__before';
229        _this.parentElement.insertBefore(_menuBefore, _this);
230
231        const iconX = _this.querySelector('.offset-icon');
232        let icon = document.querySelector('.business-line .offset-icon');
233        let closeByEnter = false;
234
235        const applyCloseStyles = () => {
236            const _classList = _this.classList;
237            _classList.add('sc-mobile-nav--close');
238            _menuBefore.style.right = '100%';
239            _bm.classList.remove('height-constraint-for-modal');
240            mobileMenuFocusTrap.deactivate();
241            const blNav = document.querySelector('#business-line-navigation');
242            if (blNav) {
243                blNav.removeAttribute('aria-hidden');
244                toggleFocusable(blNav, true);
245            }
246            _this.setAttribute('aria-hidden', 'true');
247            toggleFocusable(_this, false);
248            icon.setAttribute('aria-expanded', 'false');
249        };
250        const onEscapeKeyDown = function (event) {
251            const _classList = _this.classList;
252            if (event.key === 'Escape' && !_classList.contains('sc-mobile-nav--close')) {
253                applyCloseStyles();
254                icon.focus();
255                document.removeEventListener('keydown', onEscapeKeyDown);
256            }
257            document.body.scrollTo(0, 0);
258        };
259        const openMobileNavigation = (focusFirstMenuElement = false) => {
260            const _classList = _this.classList;
261            _classList.remove('sc-mobile-nav--close');
262            _menuBefore.style.right = 0;
263            _bm.classList.add('height-constraint-for-modal');
264            if (focusFirstMenuElement) {
265                document.querySelector('.sc-mobile-nav .business-line--secondary a').focus();
266            }
267            mobileMenuFocusTrap.activate();
268            icon.setAttribute('aria-expanded', 'true');
269            const blNav = document.querySelector('#business-line-navigation');
270            if (blNav) {
271                blNav.setAttribute('aria-hidden', 'true');
272                toggleFocusable(blNav, false);
273            }
274            _this.removeAttribute('aria-hidden');
275            toggleFocusable(_this, true);
276            document.addEventListener('keydown', onEscapeKeyDown);
277        };
278        const closeMobileNavigation = () => {
279            applyCloseStyles();
280            document.removeEventListener('keydown', onEscapeKeyDown);
281        };
282
283        const iconOnClick = function (event) {
284            event.preventDefault();
285            const _classList = _this.classList;
286            if (_classList.contains('sc-mobile-nav--close')) {
287                openMobileNavigation();
288            } else {
289                closeMobileNavigation();
290                if (closeByEnter) {
291                    icon.focus();
292                }
293            }
294            closeByEnter = false;
295            document.body.scrollTo(0, 0);
296        };
297
298        const menuKeyboardHandling = function (event) {
299            const _classList = _this.classList;
300
301            if (event.key === ' ' && _classList.contains('sc-mobile-nav--close')) {
302                openMobileNavigation();
303            } else if (event.key === ' ' && !_classList.contains('sc-mobile-nav--close')) {
304                closeMobileNavigation();
305            } else if (event.key === 'Enter') {
306                closeByEnter = true;
307            }
308            document.body.scrollTo(0, 0);
309        };
310
311        if (!icon) {
312            const _nav = document.querySelector('.business-line nav');
313            const { mobileMenuOpenText, mobileMenuCloseText } = iconX.dataset;
314            icon = iconX.cloneNode(true);
315            if (!isAfterModifications) {
316                _nav.insertBefore(icon, _nav.firstChild);
317            } else {
318                const navWrapper = _nav.parentNode;
319                navWrapper.insertBefore(icon, navWrapper.firstChild);
320            }
321            if (mobileMenuOpenText) {
322                icon.setAttribute('aria-label', mobileMenuOpenText);
323                iconX.removeAttribute('data-mobile-menu-open-text');
324            }
325            if (mobileMenuCloseText) {
326                iconX.setAttribute('aria-label', mobileMenuCloseText);
327                iconX.removeAttribute('data-mobile-menu-close-text');
328            }
329        }
330        icon.addEventListener('keydown', menuKeyboardHandling);
331        icon.addEventListener('click', iconOnClick);
332        icon.classList.add('icon--ci-menu');
333        icon.classList.remove('icon--f-map-list');
334        icon.setAttribute('aria-haspopup', 'true');
335        icon.setAttribute('aria-expanded', 'false');
336        icon.setAttribute('aria-controls', 'mobile-navigation');
337        iconX.addEventListener('keydown', menuKeyboardHandling);
338        iconX.addEventListener('click', iconOnClick);
339
340        if (window.location.search.indexOf('menu=open') !== -1) {
341            const _classList = _this.classList;
342            if (_classList.contains('sc-mobile-nav--close')) {
343                _classList.remove('sc-mobile-nav--close');
344                _menuBefore.style.right = 0;
345                _bm.classList.add('height-constraint-for-modal');
346                mobileMenuFocusTrap.activate();
347            }
348            document.body.scrollTo(0, 0);
349        }
350
351        if (_buttons) {
352            const _btnList = _buttons.querySelectorAll('.bmp-btn:not(.modal-trigger)');
353            Array.from(_btnList)
354                .reverse()
355                .map((elem) => {
356                    const newNode = elem.cloneNode(true);
357                    _buttonsNavCon.appendChild(newNode);
358                    return newNode;
359                });
360            _buttonsNavCon.dataset.height = Math.ceil(_buttonsNavCon.offsetHeight / 10);
361        }
362
363        const _heightCup =
364            parseInt(_businessLineList[1].dataset.height, 10) +
365            parseInt(_buttonsNavCon.dataset.height, 10) +
366            8;
367        _businessLineList[0].dataset.heightCup = Math.floor(
368            parseInt(_businessLineList[0].dataset.height, 10) / 100,
369        );
370
371        _bm.classList.add(`height-constraint-for-modal--${Math.ceil(_heightCup / 10)}`);
372        _bm.dataset.heightCup = Math.ceil(_heightCup / 10);
373
374        const _logoLink = document.querySelector('.header__logo');
375        const _logoLinkDesc = _logoLink ? _logoLink.querySelector('.acc-hide') : null;
376        if (_logoLinkDesc != null) {
377            if (document.documentElement.lang !== 'pl-PL') {
378                _logoLinkDesc.innerHTML = 'Bank Millennium home page';
379            } else {
380                _logoLinkDesc.innerHTML = 'Strona główna Bank Millennium';
381            }
382        }
383
384        document.querySelectorAll('.sc-mobile-nav .buttons a').forEach((elem) => {
385            if (elem.classList.contains('acc-hide')) {
386                elem.setAttribute('tabindex', '-1');
387            }
388        });
389
390        window.addEventListener('resize', () => {
391            if (window.innerWidth < 980) {
392                toggleFocusable(document.querySelector('#navi'), false);
393            } else {
394                toggleFocusable(document.querySelector('#navi'), true);
395            }
396        });
397
398        const menuSkipLink = document.querySelector('.bmp-skip-links a[href="#navi"]');
399        if (menuSkipLink) {
400            const openMobileMenuFromSkiplink = (e) => {
401                if (window.innerWidth < 980) {
402                    e.preventDefault();
403                    openMobileNavigation(true);
404                }
405            };
406            menuSkipLink.addEventListener('click', openMobileMenuFromSkiplink);
407            menuSkipLink.addEventListener('touchstart', openMobileMenuFromSkiplink);
408        }
409    }
410})('.header__business-line', '.navbar.navbar--secondary', '.logo-and-buttons .buttons-group');

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.