PageSourceSearch

https://www.financialinvestigator.is/ui/financial-investigator/droplets/easyAccessNav/easyAccessNav.js

js financialinvestigator.is collected 2026-10-08 07:45:44 UTC 11,081 bytes, 367 lines download raw bytes

1(function () {
2    'use strict';
3
4    define(function () {
5
6        /**
7         * @param {string} selector
8         * @param {Object} options
9         * @constructor
10         */
11        var easyAccessNav = function (selector, options) {
12            /** {Object} */
13            var settings = {};
14            /** {Object} */
15            var storage = {
16                isOpen: false,
17                preventClick: false
18            };
19
20            // Settings
21            options = (options) ? options : {};
22            settings.openClass = (options.openClass) ? options.openClass : 'open';
23            settings.hoverDelay = (options.hoverDelay) ? options.hoverDelay : 300;
24            settings.openOnHover = (options.openOnHover === false) ? options.openOnHover : true;
25            settings.useCategoryAsPage = (options.useCategoryAsPage) ? options.useCategoryAsPage : false;
26            settings.closeOnPageClick = (options.closeOnPageClick === false) ? options.closeOnPageClick : true;
27
28            if (options.verticalMenu) {
29                settings.openOnHover = false;
30                settings.useCategoryAsPage = false;
31                settings.closeOnPageClick = false;
32            }
33
34            // Elements
35            storage.navElement = document.querySelector(selector);
36
37            if (!storage.navElement) {
38                return;
39            }
40
41            // Events
42            document.addEventListener('touchstart', registerEventType);
43            document.addEventListener('touchend', handleEvent);
44            document.addEventListener('mouseup', handleEvent);
45            document.addEventListener('keyup', handleEvent);
46            document.addEventListener('mouseover', handleEvent);
47            document.addEventListener('click', handleClickEvent);
48
49            /**
50             * @param {Event} event
51             */
52            function registerEventType (event) {
53                // Register touch - multiple events will be fired after it, which we need to prevent
54                if (event.type === 'touchstart') {
55                    storage.ignoreNonTouchEvents = true;
56                }
57            }
58
59            /**
60             * @param {Event} event
61             */
62            function handleEvent (event) {
63                // Reset touch event check - 'mouseup' is the last event fired with touch
64                if (storage.ignoreNonTouchEvents && event.type === 'mouseup') {
65                    storage.ignoreNonTouchEvents = false;
66                    return;
67                }
68
69                // Prevent multiple events firing in case of touch
70                if (storage.ignoreNonTouchEvents && event.type !== 'touchend') {
71                    return;
72                }
73
74                var element = (event.type === 'keyup') ? document.activeElement : event.target;
75
76                switch (event.type) {
77                    case 'touchend':
78                        handleTouchEnd(element);
79                        break;
80                    case 'mouseup':
81                        handleMouseUp(element);
82                        break;
83                    case 'keyup':
84                        handleKeyUp(element);
85                        break;
86                    case 'mouseover':
87                        handleMouseOver(element);
88                        break;
89                }
90            }
91
92            /**
93             * @param {Event} event
94             */
95            function handleClickEvent (event) {
96                var element = event.target;
97                if (!isAnchorInNav(element)) {
98                    return;
99                }
100
101                if (storage.preventClick) {
102                    event.preventDefault();
103                    storage.preventClick = false;
104                }
105            }
106
107            /**
108             * @param {Element} element
109             */
110            function handleTouchEnd (element) {
111                var isLinkInNav = isAnchorInNav(element);
112
113                if (settings.closeOnPageClick && !isLinkInNav) {
114                    closeSubmenu(event);
115                    return;
116                }
117
118                if (!isLinkInNav) {
119                    return;
120                }
121
122                if (!hasSubmenu(element)) {
123                    return;
124                }
125
126                if (!settings.useCategoryAsPage) {
127                    storage.preventClick = true;
128                }
129
130                if (!hasOpenClass(element)) {
131                    storage.preventClick = true;
132                    openSubmenu(element);
133                    return;
134                }
135
136                if (!settings.useCategoryAsPage) {
137                    closeSubmenu();
138                }
139            }
140
141            /**
142             * @param {Element} element
143             */
144            function handleMouseUp (element) {
145                var isLinkInNav = isAnchorInNav(element);
146
147                if (settings.closeOnPageClick && !isLinkInNav) {
148                    closeSubmenu(event);
149                    return;
150                }
151
152                if (!isLinkInNav) {
153                    return;
154                }
155
156                if (!hasSubmenu(element)) {
157                    return;
158                }
159
160                if (!settings.useCategoryAsPage) {
161                    storage.preventClick = true;
162                }
163
164                if (settings.openOnHover) {
165                    return;
166                }
167
168                if (!hasOpenClass(element)) {
169                    openSubmenu(element);
170                    return;
171                }
172
173                if (!settings.useCategoryAsPage) {
174                    closeSubmenu();
175                }
176            }
177
178            /**
179             * @param {Element} element
180             */
181            function handleKeyUp (element) {
182                if (!isAnchorInNav(element)) {
183                    closeSubmenu();
184                    return;
185                }
186
187                openSubmenu(element);
188            }
189
190            /**
191             * @param {Element} element
192             */
193            function handleMouseOver (element) {
194                if (!settings.openOnHover) {
195                    return;
196                }
197
198                if (!isElementInNav(element)) {
199                    closeSubmenuWithDelay();
200                    return;
201                }
202
203                if (!hasSubmenu(element) && !isSubmenuElement(element)) {
204                    closeSubmenuWithDelay();
205                    return;
206                }
207
208                clearHoverTimeout();
209
210                if (!hasOpenClass(element)) {
211                    openSubmenu(element);
212                    return;
213                }
214
215                if (!settings.useCategoryAsPage) {
216                    closeSubmenu();
217                }
218            }
219
220            /**
221             * @param {Element} element
222             */
223            function openSubmenu (element) {
224                removeOpenClasses();
225                addOpenClassToParents(element);
226            }
227
228            /**
229             * Close submenu
230             */
231            function closeSubmenu () {
232                if (!storage.isOpen) {
233                    return;
234                }
235
236                removeOpenClasses();
237            }
238
239            /**
240             * Close submenu with a delay
241             */
242            function closeSubmenuWithDelay () {
243                if (!storage.isOpen) {
244                    return;
245                }
246
247                clearHoverTimeout();
248                storage.hoverTimeoutID = window.setTimeout(function () {
249                    removeOpenClasses();
250                }, settings.hoverDelay);
251            }
252
253            /**
254             * Clear hover timeout
255             */
256            function clearHoverTimeout () {
257                if (typeof storage.hoverTimeoutID === 'number') {
258                    window.clearTimeout(storage.hoverTimeoutID);
259                    delete storage.hoverTimeoutID;
260                }
261            }
262
263            /**
264             * @param {Object} element
265             */
266            function addOpenClassToParents (element) {
267                element = getCorrectParentIgnoringNormalLinks(element);
268
269                while (element && element !== storage.navElement) {
270                    if (element.tagName.toUpperCase() === 'LI') {
271                        element.classList.add(settings.openClass);
272                        storage.isOpen = true;
273                    }
274
275                    element = element.parentElement;
276                }
277            }
278
279            /**
280             * Remove all open classes
281             */
282            function removeOpenClasses () {
283                var openElements = storage.navElement.querySelectorAll('.' + settings.openClass);
284                var i;
285
286                for (i = 0; i < openElements.length; i++) {
287                    openElements[i].classList.remove(settings.openClass);
288                }
289
290                storage.isOpen = false;
291            }
292
293            /**
294             * @param element
295             * @returns {Element}
296             */
297            function getCorrectParentIgnoringNormalLinks (element) {
298                if (element.tagName.toUpperCase() === 'A' && !element.classList.contains('sub')) {
299                    return element.parentElement.parentElement;
300                }
301
302                return element.parentElement;
303            }
304
305            /**
306             * @param {Element} element
307             * @returns {boolean}
308             */
309            function isAnchorInNav (element) {
310                if (element.tagName.toUpperCase() !== 'A') {
311                    return false;
312                }
313
314                return storage.navElement.contains(element);
315            }
316
317            /**
318             * @param {Element} element
319             * @returns {boolean}
320             */
321            function isElementInNav (element) {
322                return storage.navElement.contains(element);
323            }
324
325            /**
326             * @param {Element} element
327             * @returns {boolean}
328             */
329            function isSubmenuElement (element) {
330                var i = 0;
331
332                while (element && element !== storage.navElement) {
333                    if (element.tagName.toUpperCase() === 'UL') {
334                        i++;
335                    }
336
337                    if (i === 2) {
338                        return true;
339                    }
340
341                    element = element.parentElement;
342                }
343
344                return false;
345            }
346
347            /**
348             * @param element
349             * @returns {boolean}
350             */
351            function hasSubmenu (element) {
352                return element.classList.contains('sub');
353            }
354
355            /**
356             * @param element
357             * * @returns {boolean}
358             */
359            function hasOpenClass (element) {
360                return element.parentElement && element.parentElement.classList.contains(settings.openClass);
361            }
362        };
363
364        return easyAccessNav;
365
366    });
367})();

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.