11/* eslint-disable no-undef */
2- import { initSearch , searchLandmarks , getUserLocation } from './search.js' ;
2+ import {
3+ initSearch ,
4+ searchLandmarks ,
5+ getUserLocation ,
6+ searchAirport ,
7+ openInternetRadio ,
8+ } from './search.js' ;
39import { initLandmark } from './landmark.js' ;
410import {
511 getConfig ,
@@ -16,11 +22,11 @@ import { i18n, initi18n, updateTranslation } from './lion.js';
1622
1723const translationMap = {
1824 // mapping DOM selectors to translation keys
19- '.loading-text' : { property : 'textContent' , key : 'app.loading_text' } ,
20- '.caching-text' : { property : 'textContent' , key : 'app.caching_text' } ,
25+ '.loading-text' : { property : 'textContent' , strkey : 'app.loading_text' } ,
26+ '.caching-text' : { property : 'textContent' , strkey : 'app.caching_text' } ,
2127 'input#search-input' : {
2228 property : 'placeholder' ,
23- key : 'app.search_placeholder' ,
29+ strkey : 'app.search_placeholder' ,
2430 } ,
2531} ;
2632
@@ -33,6 +39,9 @@ const settingsButton = document.getElementById('settings-button');
3339const localeButton = document . getElementById ( 'locale-button' ) ;
3440const searchSideBar = document . getElementById ( 'search-bar-container' ) ;
3541const landmarkSidebar = document . getElementById ( 'landmarks-sidebar' ) ;
42+ const moreWrapper = document . getElementById ( 'more-wrapper' ) ;
43+ const moreButton = document . getElementById ( 'more-button' ) ;
44+ const moreMenu = document . getElementById ( 'more-menu' ) ;
3645
3746// Default coordinates (San Francisco)
3847let defaultLocation = { lat : 37.7749 , lng : - 122.4194 } ;
@@ -144,16 +153,43 @@ async function initMap() {
144153 setLoading ( false ) ;
145154}
146155
156+ /**
157+ * Adds a new option to More-menu dropdown.
158+ * @param {string } strkey - The translation key for this label.
159+ * @param {Function } handler - Function called when the option is clicked.
160+ */
161+ export function addMoreOption ( strkey , handler ) {
162+ const item = document . createElement ( 'div' ) ;
163+ item . className = 'dropdown-item' ;
164+ item . setAttribute ( 'data-i18n-text' , strkey ) ;
165+ item . addEventListener ( 'click' , ( ev ) => {
166+ handler ( ev ) ;
167+ moreMenu . classList . remove ( 'show' ) ; // hide after selection
168+ } ) ;
169+ moreMenu . appendChild ( item ) ;
170+ }
171+
172+ // when clicking elsewhere on the document
173+ document . addEventListener ( 'click' , ( ) => {
174+ moreMenu . classList . remove ( 'show' ) ;
175+ } ) ;
176+
147177/**
148178 * Set up custom controls
149179 */
150180async function setupCustomControl ( ) {
181+ // add each button into gmap DOM structure, attaching click listeners
151182 map . controls [ google . maps . ControlPosition . RIGHT_BOTTOM ] . push ( myLocationButton ) ;
152183 myLocationButton . addEventListener ( 'click' , async ( ) => {
153184 await markUserLocation ( ) ;
154185 } ) ;
155186
156- // Add click event to search landmarks button
187+ map . controls [ google . maps . ControlPosition . RIGHT_BOTTOM ] . push ( moreWrapper ) ;
188+ moreButton . addEventListener ( 'click' , ( ev ) => {
189+ ev . stopPropagation ( ) ; // Prevent click bubbling
190+ moreMenu . classList . toggle ( 'show' ) ;
191+ } ) ;
192+
157193 map . controls [ google . maps . ControlPosition . RIGHT_BOTTOM ] . push (
158194 searchLandmarksButton
159195 ) ;
@@ -178,9 +214,13 @@ async function setupCustomControl() {
178214 if ( i18n . lang . secondLocale ) {
179215 map . controls [ google . maps . ControlPosition . LEFT_BOTTOM ] . push ( localeButton ) ;
180216 localeButton . addEventListener ( 'click' , async ( ) => {
181- if ( i18n . userLocale === i18n . lang . preferLocale )
217+ if ( i18n . userLocale === i18n . lang . preferLocale ) {
182218 i18n . userLocale = i18n . lang . secondLocale ;
183- else i18n . userLocale = i18n . lang . preferLocale ;
219+ localeButton . textContent = '🌏' ;
220+ } else {
221+ i18n . userLocale = i18n . lang . preferLocale ;
222+ localeButton . textContent = '🌎' ;
223+ }
184224 // await updateTranslation();
185225 await applyTranslations ( ) ;
186226 } ) ;
@@ -257,23 +297,23 @@ function loadGoogleMapsAPI() {
257297}
258298
259299async function applyTranslations ( ) {
260- Object . entries ( translationMap ) . forEach ( ( [ selector , { property, key } ] ) => {
300+ Object . entries ( translationMap ) . forEach ( ( [ selector , { property, strkey } ] ) => {
261301 document . querySelectorAll ( selector ) . forEach ( ( el ) => {
262302 if ( property in el || property === 'textContent' ) {
263- el [ property ] = i18n . t ( key ) ;
303+ el [ property ] = i18n . t ( strkey ) ;
264304 }
265305 } ) ;
266306 } ) ;
267307
268308 document . querySelectorAll ( '[data-i18n-text]' ) . forEach ( ( el ) => {
269- const key = el . getAttribute ( 'data-i18n-text' ) ;
270- const str_value = i18n . t ( key ) ;
271- el . textContent = str_value === key ? '' : str_value ;
309+ const strkey = el . getAttribute ( 'data-i18n-text' ) ;
310+ const str_value = i18n . t ( strkey ) ;
311+ el . textContent = str_value === strkey ? '' : str_value ;
272312 } ) ;
273313
274314 document . querySelectorAll ( '[data-i18n-title]' ) . forEach ( ( el ) => {
275- const key = el . getAttribute ( 'data-i18n-title' ) ;
276- el . title = i18n . t ( key ) ; // Set title for tooltips
315+ const strkey = el . getAttribute ( 'data-i18n-title' ) ;
316+ el . title = i18n . t ( strkey ) ; // Set title for tooltips
277317 } ) ;
278318}
279319
@@ -289,6 +329,14 @@ document.addEventListener('DOMContentLoaded', async () => {
289329 // Load Google Maps API
290330 loadGoogleMapsAPI ( ) ;
291331
332+ addMoreOption ( 'app.airport_menu' , async ( ) => {
333+ await searchAirport ( ) ;
334+ } ) ;
335+
336+ addMoreOption ( 'app.radio_menu' , async ( ) => {
337+ await openInternetRadio ( ) ;
338+ } ) ;
339+
292340 // Skip auto-translation if no resource bundles are loaded
293341 if ( Object . keys ( i18n . translations ) . length > 0 ) {
294342 await updateTranslation ( ) ;
0 commit comments