PageSourceSearch

https://www.sweg.de/assets/js/language-switcher/language-switcher.js

js sweg.de collected 2026-10-02 03:27:39 UTC 3,718 bytes, 135 lines download raw bytes

1/**
2 * Adds events to interact with the language switcher.
3 * @module LanguageSwitcher
4 * @author Martin Hubrich
5 */
6
7'use strict';
8
9// Self-written modules
10import { hideNavigation } from '../nav-main/nav-main.js';
11
12// Cache all needed objects
13const body = document.querySelector('body');
14const languageSwitcher = body.querySelector('#language-switcher');
15const languageDropdownToggle = languageSwitcher !== null ? languageSwitcher.querySelector('[data-language-dropdown-toggle]') : undefined;
16const languageDropdown = languageSwitcher !== null ? languageSwitcher.querySelector('.language-switcher__dropdown') : undefined;
17const languageDropdownFirstEntry = languageDropdown !== undefined ? languageDropdown.querySelector('li:first-child a') : undefined;
18const languageDropdownLastEntry = languageDropdown !== undefined ? languageDropdown.querySelector('li:last-child a') : undefined;
19
20/**
21 * Initiates the module.
22 * @function init
23 * @public
24 */
25export default function init() {
26  if (languageSwitcher !== null) {
27    _bindEvents();
28  }
29}
30
31/**
32 * Binds all events to DOM objects.
33 * @function _bindEvents
34 * @private
35 */
36function _bindEvents() {
37  languageDropdownToggle.addEventListener('click', _handleClickEvent, false);
38
39  window.addEventListener('resize:smart', () => {
40    closeDropdown();
41  });
42
43  // Closes the dropdown if the user clicked outside the language switcher
44  body.addEventListener('click', (event) => {
45    if (!Object.is(event.target, languageSwitcher)
46        && !event.target.closest('#language-switcher')) {
47      closeDropdown();
48    }
49  }, false);
50}
51
52/**
53 * Handle events which are received by clicking the current target.
54 * @function _handleClickEvent
55 * @param {Object} event - default event object
56 * @private
57 */
58function _handleClickEvent(event) {
59  _toggleDropdownVisibility(event.currentTarget);
60}
61
62/**
63 * Handle events which are received by pressing a keyboard key.
64 * @function _handleKeyEvent
65 * @param {Object} event - default event object
66 * @private
67 */
68function _handleKeyEvent(event) {
69  let key = event.charCode ? event.charCode : event.keyCode ? event.keyCode : 0;
70
71  switch (key) {
72    case 9: // Tab
73      if (event.shiftKey) { // Check if shift is pressed
74        if (event.target === languageDropdownFirstEntry) {
75          languageDropdownLastEntry.focus();
76          event.preventDefault();
77        }
78      } else {
79        if (event.target === languageDropdownLastEntry) {
80          languageDropdownFirstEntry.focus();
81          event.preventDefault();
82        }
83      }
84      break;
85    case 27: // ESC
86      closeDropdown();
87      languageDropdownToggle.focus();
88      break;
89  }
90}
91
92/**
93 * Opens the language dropdown if it's closed and reversed.
94 * @function _toggleDropdownVisibility
95 * @param {Element} toggle - the clicked dropdown header
96 * @private
97 */
98function _toggleDropdownVisibility(toggle) {
99  if (toggle.getAttribute('aria-expanded') === 'false') {
100    hideNavigation();
101    _openDropdown();
102  } else {
103    closeDropdown();
104  }
105}
106
107/**
108 * Closes the language dropdown.
109 * @function closeDropdown
110 * @public
111 */
112export function closeDropdown() {
113  if (languageSwitcher !== null) {
114    languageDropdownToggle.setAttribute('aria-expanded', false);
115
116    window.removeEventListener('keydown', _handleKeyEvent);
117  }
118}
119
120/**
121 * Opens the language dropdown.
122 * @function _openDropdown
123 * @private
124 */
125function _openDropdown() {
126  languageDropdownToggle.setAttribute('aria-expanded', true);
127
128  // We need a small delay before setting the new focus because the element
129  // isn't visible yet. Therefore it can't be focused.
130  setTimeout(() => {
131    languageDropdownFirstEntry.focus();
132  }, 100);
133
134  window.addEventListener('keydown', _handleKeyEvent, false);
135}

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.