@bmlt-enabled/croutonjs 4.1.11 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11186,7 +11186,9 @@ function CroutonLocalization(language) {
11186
11186
  'all': 'الجميع',
11187
11187
  'menu': 'القائمة',
11188
11188
  'search for meetings': 'البحث عن الاجتماعات',
11189
+ 'search by location': 'البحث حسب الموقع',
11189
11190
  'show meetings near...': 'أظهر الاجتماعات بالقرب من...',
11191
+ 'closest meetings': 'أقرب الاجتماعات',
11190
11192
  'filter meetings': 'سرد الاجتماعات',
11191
11193
  'visible meeting list': 'قائمة الاجتماعات المرئية',
11192
11194
  'enter a city or zip code': 'أدخل المدينة أو الرمز البريدي',
@@ -11207,6 +11209,9 @@ function CroutonLocalization(language) {
11207
11209
  "waze": "وايز",
11208
11210
  "waze_desc": "فتح في تطبيق وايز",
11209
11211
  'address_lookup_fail': 'تعذر العثور على العنوان. يرجى المحاولة مرة أخرى.',
11212
+ "favorites": "المفضلة",
11213
+ "widen search": "البحث الواسع",
11214
+ "cancel search": "إلغاء البحث"
11210
11215
  },
11211
11216
  "cs": {
11212
11217
  "days_of_the_week": ["", "Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"],
@@ -11246,7 +11251,9 @@ function CroutonLocalization(language) {
11246
11251
  "all": "Jakékoli",
11247
11252
  "menu": "Menu",
11248
11253
  "search for meetings": "Hledat setkání",
11254
+ 'search by location': 'Vyhledávání podle lokality',
11249
11255
  "show meetings near...": "Setkání v jiných městech",
11256
+ 'closest meetings': "Nejbližší setkání",
11250
11257
  "filter meetings": "Filtr pro jazyk, formát atd.",
11251
11258
  "visible meeting list": "Viditelný seznam setkání jako tabulka",
11252
11259
  "enter a city or zip code": "Město nebo PSČ",
@@ -11257,7 +11264,6 @@ function CroutonLocalization(language) {
11257
11264
  "meeting details": "Podrobnosti o setkání",
11258
11265
  "report update": "Nahlásit aktualizaci",
11259
11266
  "filter by visibility": "Zobrazit pouze setkání, která jsou aktuálně na mapě",
11260
- "go": "Jít!",
11261
11267
  "get_directions": "Získat pokyny",
11262
11268
  "select_map_app": "Vyberte aplikaci pro mapy",
11263
11269
  "apple_maps": "Apple Mapy",
@@ -11272,6 +11278,9 @@ function CroutonLocalization(language) {
11272
11278
  "sorted by distance": "Seřazeno podle vzdálenosti",
11273
11279
  "address_lookup_fail": "Adresu se nepodařilo najít. Zkuste to prosím znovu.",
11274
11280
  "contact": "Kontakt",
11281
+ "favorites": "Oblíbené",
11282
+ "widen search": "Rozšířit vyhledávání",
11283
+ "cancel search": "Zrušit vyhledávání",
11275
11284
  },
11276
11285
  "da-DK": {
11277
11286
  "days_of_the_week": ["", "Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"],
@@ -11288,7 +11297,7 @@ function CroutonLocalization(language) {
11288
11297
  "formats": "Struktur",
11289
11298
  "map": "Kort",
11290
11299
  "neighborhood": "Neighborhood",
11291
- "near_me": "Find nearby meetings",
11300
+ "near_me": "Find closest meetings",
11292
11301
  "text_search": "Find meetings there",
11293
11302
  "click_search": "Find meetings near to a point on the map",
11294
11303
  "pan_and_zoom": "Pan + Zoom",
@@ -11318,7 +11327,9 @@ function CroutonLocalization(language) {
11318
11327
  'menu': 'Menu',
11319
11328
  "bmlt2ics": "Add to your calendar",
11320
11329
  'search for meetings': 'Search for meetings',
11330
+ 'search by location': 'Søg efter placering',
11321
11331
  'show meetings near...': 'Show meetings near...',
11332
+ 'closest meetings': 'Nærmeste møder',
11322
11333
  'filter meetings': 'Filter meetings',
11323
11334
  'visible meeting list': 'Visible meetings as list',
11324
11335
  'enter a city or zip code': 'Enter a city or zip code',
@@ -11338,6 +11349,9 @@ function CroutonLocalization(language) {
11338
11349
  "sorted by distance": "Sorteret efter Afstand",
11339
11350
  "address_lookup_fail": "Adressen kunne ikke findes. Prøv venligst igen.",
11340
11351
  "contact": "Kontakt",
11352
+ "favorites": "Favoritter",
11353
+ "widen search": "Udvid søgning",
11354
+ "cancel search": "Annuller søgning",
11341
11355
  },
11342
11356
  "de-DE": {
11343
11357
  "days_of_the_week": ["", "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
@@ -11383,7 +11397,9 @@ function CroutonLocalization(language) {
11383
11397
  'all': 'Alle',
11384
11398
  'menu': 'Menu',
11385
11399
  'search for meetings': 'Search for meetings',
11400
+ 'search by location': 'Suche nach Standort',
11386
11401
  'show meetings near...': 'Meetings in andere Städten',
11402
+ 'closest meetings': 'Nächstgelegene Meetings',
11387
11403
  'filter meetings': 'Filter für Sprache, Format usw.',
11388
11404
  'visible meeting list': 'Sichtbare Meetings als Tabelle',
11389
11405
  'enter a city or zip code': 'Stadt oder PLZ',
@@ -11394,7 +11410,6 @@ function CroutonLocalization(language) {
11394
11410
  'meeting details': "Genaueres zum Meeting",
11395
11411
  'report update': "Report an Update",
11396
11412
  'filter by visibility': "Zeige nur Meetings, die gerade auf dem Karte stehen",
11397
- 'go': "Los!",
11398
11413
  "get_directions": "Wegbeschreibung",
11399
11414
  "select_map_app": "Karten-App auswählen",
11400
11415
  "apple_maps": "Apple Maps",
@@ -11412,6 +11427,9 @@ function CroutonLocalization(language) {
11412
11427
  "distance": "Entfernung",
11413
11428
  "all meetings": "Alle Meetings",
11414
11429
  'upcoming meetings': "Nächste 24 Stunden",
11430
+ "favorites": "Favoriten",
11431
+ "widen search": "Suche ausweiten",
11432
+ "cancel search": "Abbrechen",
11415
11433
  },
11416
11434
  'el-GR': {
11417
11435
  "days_of_the_week": ["", "Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο"],
@@ -11457,7 +11475,9 @@ function CroutonLocalization(language) {
11457
11475
  "all": "",
11458
11476
  "menu": "Μενού",
11459
11477
  "search for meetings": "Αναζήτηση ομάδων",
11478
+ 'search by location': 'Αναζήτηση ανά τοποθεσία',
11460
11479
  "show meetings near...": "Εμφάνιση ομάδων κοντά σε..",
11480
+ "closest meetings": "Πλησιέστερες Συναντήσεις",
11461
11481
  "filter meetings": "Φίλτραρε τις ομάδες",
11462
11482
  "visible meeting list": "Λίστα ορατών ομάδων",
11463
11483
  "enter a city or zip code": "Εισαγάγετε μια πόλη ή ταχυδρομικό κώδικα",
@@ -11469,7 +11489,6 @@ function CroutonLocalization(language) {
11469
11489
  "report update": "Ανέφερε ενημέρωση",
11470
11490
  "filter by visibility": "Φίλτραρε ανα ορατές ομάδες",
11471
11491
  "open search dialog": "’νοιξε αναζήτηση",
11472
- "go": "Έναρξη",
11473
11492
  "get_directions": "Λάβετε οδηγίες",
11474
11493
  "select_map_app": "Διαλέξτε εφαρμογή χάρτη",
11475
11494
  "apple_maps": "Χάρτες Apple",
@@ -11504,6 +11523,9 @@ function CroutonLocalization(language) {
11504
11523
  "meets virtually and in person": "Διαδικτυακή και φυσική ομάδα",
11505
11524
  "all meetings": "Όλες οι ομάδες",
11506
11525
  "upcoming meetings": "Προσεχείς ομάδες",
11526
+ "favorites": "Αγαπημένα",
11527
+ "widen search": "Διεύρυνση αναζήτησης",
11528
+ "cancel search": "Ακύρωση αναζήτησης",
11507
11529
  },
11508
11530
  "en-AU": {
11509
11531
  "days_of_the_week": ["", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
@@ -11520,7 +11542,7 @@ function CroutonLocalization(language) {
11520
11542
  "formats": "Formats",
11521
11543
  "map": "Map",
11522
11544
  "neighborhood": "Neighbourhood",
11523
- "near_me": "Find nearby meetings",
11545
+ "near_me": "Find closest meetings",
11524
11546
  "text_search": "Find meetings there",
11525
11547
  "click_search": "Find meetings near to a point on the map",
11526
11548
  "languages": "Languages",
@@ -11549,7 +11571,9 @@ function CroutonLocalization(language) {
11549
11571
  'all': 'All',
11550
11572
  'menu': 'Menu',
11551
11573
  'search for meetings': 'Search for meetings',
11574
+ 'search by location': 'Search by Location',
11552
11575
  'show meetings near...': 'Show meetings near...',
11576
+ 'closest meetings': "Closest Meetings",
11553
11577
  'filter meetings': 'Filter meetings',
11554
11578
  'visible meeting list': 'Visible meetings as list',
11555
11579
  'enter a city or zip code': 'Enter a city and state',
@@ -11572,6 +11596,9 @@ function CroutonLocalization(language) {
11572
11596
  "zoomed-out-message": "We can't search the entire area for meetings. Please zoom in or do a new search.",
11573
11597
  "sorted by distance": "Sorted by Distance",
11574
11598
  "address_lookup_fail": "The address could not be found. Please try again.",
11599
+ "favorites": "Favorites",
11600
+ "widen search": "Widen Search",
11601
+ "cancel search": "Cancel Search",
11575
11602
  },
11576
11603
  "en-CA": {
11577
11604
  "days_of_the_week": ["", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
@@ -11588,7 +11615,7 @@ function CroutonLocalization(language) {
11588
11615
  "formats": "Formats",
11589
11616
  "map": "Map",
11590
11617
  "neighborhood": "Neighborhood",
11591
- "near_me": "Find nearby meetings",
11618
+ "near_me": "Find closest meetings",
11592
11619
  "text_search": "Find meetings there",
11593
11620
  "click_search": "Find meetings near to a point on the map",
11594
11621
  "pan_and_zoom": "Pan + Zoom",
@@ -11617,7 +11644,9 @@ function CroutonLocalization(language) {
11617
11644
  'all': 'All',
11618
11645
  'menu': 'Menu',
11619
11646
  'search for meetings': 'Search for meetings',
11647
+ 'search by location': 'Search by Location',
11620
11648
  'show meetings near...': 'Show meetings near...',
11649
+ 'closest meetings': "Closest Meetings",
11621
11650
  'filter meetings': 'Filter meetings',
11622
11651
  'visible meeting list': 'Visible meetings as list',
11623
11652
  'enter a city or zip code': 'Enter a city or zip code',
@@ -11641,6 +11670,9 @@ function CroutonLocalization(language) {
11641
11670
  "zoomed-out-message": "We can't search the entire area for meetings. Please zoom in or do a new search.",
11642
11671
  "sorted by distance": "Sorted by Distance",
11643
11672
  "address_lookup_fail": "The address could not be found. Please try again.",
11673
+ "favorites": "Favorites",
11674
+ "widen search": "Widen Search",
11675
+ "cancel search": "Cancel Search",
11644
11676
  },
11645
11677
  "en-NZ": {
11646
11678
  "days_of_the_week": ["", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
@@ -11657,7 +11689,7 @@ function CroutonLocalization(language) {
11657
11689
  "formats": "Formats",
11658
11690
  "map": "Map",
11659
11691
  "neighborhood": "Neighborhood",
11660
- "near_me": "Find nearby meetings",
11692
+ "near_me": "Find closest meetings",
11661
11693
  "text_search": "Find meetings there",
11662
11694
  "click_search": "Find meetings near to a point on the map",
11663
11695
  "pan_and_zoom": "Pan + Zoom",
@@ -11686,7 +11718,9 @@ function CroutonLocalization(language) {
11686
11718
  'all': 'All',
11687
11719
  'menu': 'Menu',
11688
11720
  'search for meetings': 'Search for meetings',
11721
+ 'search by location': 'Search by Location',
11689
11722
  'show meetings near...': 'Show meetings near...',
11723
+ 'closest meetings': "Closest Meetings",
11690
11724
  'filter meetings': 'Filter meetings',
11691
11725
  'visible meeting list': 'Visible meetings as list',
11692
11726
  'enter a city or zip code': 'Enter a city or zip code',
@@ -11710,6 +11744,9 @@ function CroutonLocalization(language) {
11710
11744
  "zoomed-out-message": "We can't search the entire area for meetings. Please zoom in or do a new search.",
11711
11745
  "sorted by distance": "Sorted by Distance",
11712
11746
  "address_lookup_fail": "The address could not be found. Please try again.",
11747
+ "favorites": "Favorites",
11748
+ "widen search": "Widen Search",
11749
+ "cancel search": "Cancel Search",
11713
11750
  },
11714
11751
  "en-UK": {
11715
11752
  "days_of_the_week": ["", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
@@ -11726,7 +11763,7 @@ function CroutonLocalization(language) {
11726
11763
  "formats": "Formats",
11727
11764
  "map": "Map",
11728
11765
  "neighborhood": "Neighborhood",
11729
- "near_me": "Find nearby meetings",
11766
+ "near_me": "Find closest meetings",
11730
11767
  "text_search": "Find meetings there",
11731
11768
  "click_search": "Find meetings near to a point on the map",
11732
11769
  "pan_and_zoom": "Pan + Zoom",
@@ -11756,7 +11793,9 @@ function CroutonLocalization(language) {
11756
11793
  'menu': "Menu",
11757
11794
  "bmlt2ics": "Add to your calendar",
11758
11795
  'search for meetings': 'Search for meetings',
11796
+ 'search by location': 'Search by Location',
11759
11797
  'show meetings near...': 'Show meetings near...',
11798
+ 'closest meetings': "Closest Meetings",
11760
11799
  'filter meetings': 'Filter meetings',
11761
11800
  'visible meeting list': 'Visible meetings as list',
11762
11801
  'enter a city or zip code': 'Enter a city or zip code',
@@ -11779,6 +11818,9 @@ function CroutonLocalization(language) {
11779
11818
  "zoomed-out-message": "We can't search the entire area for meetings. Please zoom in or do a new search.",
11780
11819
  "sorted by distance": "Sorted by Distance",
11781
11820
  "address_lookup_fail": "The address could not be found. Please try again.",
11821
+ "favorites": "Favorites",
11822
+ "widen search": "Widen Search",
11823
+ "cancel search": "Cancel Search",
11782
11824
  },
11783
11825
 
11784
11826
  "en-US": {
@@ -11796,7 +11838,7 @@ function CroutonLocalization(language) {
11796
11838
  "formats": "Formats",
11797
11839
  "map": "Map",
11798
11840
  "neighborhood": "Neighborhood",
11799
- "near_me": "Find nearby meetings",
11841
+ "near_me": "Find closest meetings",
11800
11842
  "text_search": "Find meetings there",
11801
11843
  "click_search": "Find meetings near to a point on the map",
11802
11844
  "pan_and_zoom": "Pan + Zoom",
@@ -11825,7 +11867,9 @@ function CroutonLocalization(language) {
11825
11867
  'all': 'All',
11826
11868
  'menu': "Menu",
11827
11869
  'search for meetings': 'Search for meetings',
11870
+ 'search by location': 'Search by Location',
11828
11871
  'show meetings near...': 'Show meetings near...',
11872
+ 'closest meetings': "Closest Meetings",
11829
11873
  'filter meetings': 'Filter meetings',
11830
11874
  'visible meeting list': 'Visible meetings as list',
11831
11875
  'enter a city or zip code': 'Enter a city or zip code',
@@ -11872,6 +11916,10 @@ function CroutonLocalization(language) {
11872
11916
  "more info": "More Info",
11873
11917
  "all meetings": "All Meetings",
11874
11918
  'upcoming meetings': "Upcoming Meetings",
11919
+ "favorites": "Favorites",
11920
+ "choose one": "Choose one:",
11921
+ "widen search": "Widen Search",
11922
+ "cancel search": "Cancel Search",
11875
11923
  },
11876
11924
  "es-US": {
11877
11925
  "days_of_the_week": ["", "Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"],
@@ -11918,7 +11966,9 @@ function CroutonLocalization(language) {
11918
11966
  'all': 'Todos',
11919
11967
  'menu': "Menú",
11920
11968
  'search for meetings': 'Buscar reuniones',
11969
+ 'search by location': 'Buscar por ubicación',
11921
11970
  'show meetings near...': 'Mostrar reuniones cercanas...',
11971
+ 'closest meetings': 'Reuniones más cercanas',
11922
11972
  'filter meetings': 'Filtrar reuniones',
11923
11973
  'visible meeting list': 'Listado visible de reuniones',
11924
11974
  'enter a city or zip code': 'Introduce una ciudad o un código postal',
@@ -11942,6 +11992,9 @@ function CroutonLocalization(language) {
11942
11992
  "zoomed-out-message": "No podemos buscar reuniones en toda la zona. Por favor, acérquese o haga una nueva búsqueda.",
11943
11993
  "sorted by distance": "Ordenado por distancia",
11944
11994
  "address_lookup_fail": "The address could not be found. Please try again.",
11995
+ "favorites": "Favoritos",
11996
+ "widen search": "Búsqueda amplia",
11997
+ "cancel search": "Cancelar búsqueda",
11945
11998
  },
11946
11999
  "fa-IR": {
11947
12000
  "days_of_the_week": ["", 'یَکشَنب', 'دوشَنبه', 'سه‌شنبه', 'چهار شنبه', 'پَنج شَنبه', 'جُمعه', 'شَنبه'],
@@ -11994,7 +12047,9 @@ function CroutonLocalization(language) {
11994
12047
  "all": "همه",
11995
12048
  "menu": " منوی",
11996
12049
  "search for meetings": "جستجوی جلسه ها",
12050
+ 'search by location': 'جستجو بر اساس مکان',
11997
12051
  "show meetings near...": "نمایش جلسات نزدیک",
12052
+ "closest meetings": "نزدیک ترین ملاقات ها",
11998
12053
  "filter meetings": "فیلتر جلسات",
11999
12054
  "visible meeting list": "جلسات قابل مشاهده به عنوان لیست",
12000
12055
  "enter a city or zip code": "شهر یا کد پستی را وارد کنید",
@@ -12005,7 +12060,6 @@ function CroutonLocalization(language) {
12005
12060
  "meeting details": "جزئیات جلسه",
12006
12061
  "report update": "گزارش به‌روزرسانی",
12007
12062
  "filter by visibility": "فقط این جلسات را فهرست کنید",
12008
- "go": "برو",
12009
12063
  "distance": "فاصله",
12010
12064
  "get_directions": "دریافت مسیر",
12011
12065
  "select_map_app": "انتخاب برنامه نقشه",
@@ -12024,6 +12078,9 @@ function CroutonLocalization(language) {
12024
12078
  'comments': 'توضیحات',
12025
12079
  'group details': 'نمایش گروه',
12026
12080
  "address_lookup_fail": "آدرس پیدا نشد. لطفا دوباره تلاش کنید.",
12081
+ "favorites": "مورد علاقه",
12082
+ "widen search": "جستجوی گسترده",
12083
+ "cancel search": "لغو جستجو",
12027
12084
  },
12028
12085
  "fr-CA": {
12029
12086
  "days_of_the_week": ["", "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
@@ -12069,7 +12126,9 @@ function CroutonLocalization(language) {
12069
12126
  "all": "Tout",
12070
12127
  "menu": "Menu",
12071
12128
  "search for meetings": "Rechercher des réunions",
12129
+ 'search by location': 'Recherche par localisation',
12072
12130
  "show meetings near...": "Afficher les réunions près de...",
12131
+ "closest meetings": "Réunions les plus proches",
12073
12132
  "filter meetings": "Filtrer les réunions",
12074
12133
  "visible meeting list": "Liste des réunions visibles",
12075
12134
  "enter a city or zip code": "Entrer une ville ou un code postal",
@@ -12092,6 +12151,9 @@ function CroutonLocalization(language) {
12092
12151
  "waze_desc": "Ouvrir dans l'application Waze",
12093
12152
  "sorted by distance": "Trié par distance",
12094
12153
  "address_lookup_fail": "L'adresse est introuvable. Veuillez réessayer.",
12154
+ "favorites": "Favoris",
12155
+ "widen search": "Recherche élargie",
12156
+ "cancel search": "Annuler la recherche",
12095
12157
  },
12096
12158
  "it-IT": {
12097
12159
  "days_of_the_week": ["", "Domenica", " Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
@@ -12137,7 +12199,9 @@ function CroutonLocalization(language) {
12137
12199
  'all': 'Tutti',
12138
12200
  'menu': "Menu",
12139
12201
  'search for meetings': 'Search for meetings',
12202
+ 'search by location': 'Cerca per posizione',
12140
12203
  'show meetings near...': 'Mostra incontri nelle vicinanze..',
12204
+ 'closest meetings': "Riunioni più ravvicinati",
12141
12205
  'filter meetings': 'Filtrare le riunioni',
12142
12206
  'visible meeting list': 'Elenco riunioni visibile',
12143
12207
  'enter a city or zip code': 'Inserire una città o un codice postale',
@@ -12160,6 +12224,9 @@ function CroutonLocalization(language) {
12160
12224
  "waze_desc": "Apri nell'app Waze",
12161
12225
  "sorted by distance": "Ordinati per distanza",
12162
12226
  "address_lookup_fail": "L'indirizzo non è stato trovato. Per favore riprova.",
12227
+ "favorites": "Preferiti",
12228
+ "widen search": "Ricerca larga",
12229
+ "cancel search": "Annulla ricerca",
12163
12230
  },
12164
12231
  "nl-NL": {
12165
12232
  "days_of_the_week": ["", "Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"],
@@ -12205,6 +12272,7 @@ function CroutonLocalization(language) {
12205
12272
  'all': 'All',
12206
12273
  'menu': "Menu",
12207
12274
  'search for meetings': 'Search for meetings',
12275
+ 'search by location': 'Search by Location',
12208
12276
  'show meetings near...': 'Show meetings near...',
12209
12277
  'filter meetings': 'Filter meetings',
12210
12278
  'visible meeting list': 'Visible meetings as list',
@@ -12272,6 +12340,7 @@ function CroutonLocalization(language) {
12272
12340
  'all': 'All',
12273
12341
  'menu': "Menu",
12274
12342
  'search for meetings': 'Search for meetings',
12343
+ 'search by location': 'Search by Location',
12275
12344
  'show meetings near...': 'Show meetings near...',
12276
12345
  'filter meetings': 'Filter meetings',
12277
12346
  'visible meeting list': 'Visible meetings as list',
@@ -12295,6 +12364,9 @@ function CroutonLocalization(language) {
12295
12364
  "waze_desc": "Otwórz w aplikacji Waze",
12296
12365
  "sorted by distance": "Posortowane według odległości",
12297
12366
  "address_lookup_fail": "The address could not be found. Please try again.",
12367
+ "favorites": "Ulubione",
12368
+ "widen search": "Widen Search",
12369
+ "cancel search": "Cancel Search",
12298
12370
  },
12299
12371
  "pt-BR": {
12300
12372
  "days_of_the_week": ["", "Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"],
@@ -12341,6 +12413,7 @@ function CroutonLocalization(language) {
12341
12413
  'menu': "Menu",
12342
12414
  "bmlt2ics": "Add to your calendar",
12343
12415
  'search for meetings': 'Search for meetings',
12416
+ 'search by location': 'Search by Location',
12344
12417
  'show meetings near...': 'Show meetings near...',
12345
12418
  'filter meetings': 'Filter meetings',
12346
12419
  'visible meeting list': 'Visible meetings as list',
@@ -12363,6 +12436,9 @@ function CroutonLocalization(language) {
12363
12436
  "waze_desc": "Abrir no aplicativo Waze",
12364
12437
  "sorted by distance": "Classificado por distância",
12365
12438
  "address_lookup_fail": "The address could not be found. Please try again.",
12439
+ "favorites": "Favoritos",
12440
+ "widen search": "Widen Search",
12441
+ "cancel search": "Cancel Search",
12366
12442
  },
12367
12443
  "ru-RU": {
12368
12444
  "days_of_the_week": ["", "Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"],
@@ -12409,7 +12485,9 @@ function CroutonLocalization(language) {
12409
12485
  'menu': "Меню",
12410
12486
  "bmlt2ics": "Добавить в календарь",
12411
12487
  'search for meetings': 'Поиск собраний',
12488
+ 'search by location': 'Поиск по местонахождению',
12412
12489
  'show meetings near...': 'Показывать собрания рядом с...',
12490
+ 'closest meetings': 'Ближайшие встречи',
12413
12491
  'filter meetings': 'Фильтровать собрания',
12414
12492
  'visible meeting list': 'Собрания в виде списка',
12415
12493
  'enter a city or zip code': 'Введите город или почтовый индек',
@@ -12419,7 +12497,6 @@ function CroutonLocalization(language) {
12419
12497
  'meeting details': "Подробности собрания",
12420
12498
  'report update': "Report an Update",
12421
12499
  'filter by visibility': "List only these meetings",
12422
- 'go': "Go!",
12423
12500
  "distance": "Расстояние",
12424
12501
  "get_directions": "Проложить маршрут",
12425
12502
  "select_map_app": "Выбрать приложение карт",
@@ -12431,6 +12508,9 @@ function CroutonLocalization(language) {
12431
12508
  "waze_desc": "Открыть в приложении Waze",
12432
12509
  "sorted by distance": "Сортировка по расстоянию",
12433
12510
  "address_lookup_fail": "Адрес не найден. Пожалуйста, попробуйте еще раз.",
12511
+ "favorites": "Избранное",
12512
+ "widen search": "Расширить поиск",
12513
+ "cancel search": "Отмена поиска",
12434
12514
  },
12435
12515
  "sk": {
12436
12516
  "days_of_the_week": ["", "Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota"],
@@ -12470,7 +12550,9 @@ function CroutonLocalization(language) {
12470
12550
  "all": "Akékoľvek",
12471
12551
  "menu": "Menu",
12472
12552
  "search for meetings": "Hľadať stretnutia",
12553
+ 'search by location': 'Vyhľadávanie podľa lokality',
12473
12554
  "show meetings near...": "Stretnutia v iných mestách",
12555
+ "closest meetings": "Najbližšie stretnutia",
12474
12556
  "filter meetings": "Filter pre jazyk, formát atď.",
12475
12557
  "visible meeting list": "Viditeľné stretnutia ako tabuľka",
12476
12558
  "enter a city or zip code": "Mesto alebo PSČ",
@@ -12481,7 +12563,6 @@ function CroutonLocalization(language) {
12481
12563
  "meeting details": "Podrobnosti o stretnutí",
12482
12564
  "report update": "Nahlásiť aktualizáciu",
12483
12565
  "filter by visibility": "Zobraziť iba stretnutia, ktoré sú práve na mape",
12484
- "go": "Ísť!",
12485
12566
  "get_directions": "Získať trasu",
12486
12567
  "select_map_app": "Vyberte aplikáciu pre mapy",
12487
12568
  "apple_maps": "Apple Maps",
@@ -12495,6 +12576,9 @@ function CroutonLocalization(language) {
12495
12576
  "zoomed-out-message": "Nemôžeme prehľadať celú oblasť pre stretnutia. Prosím, priblížte alebo vykonajte nové vyhľadávanie.",
12496
12577
  "sorted by distance": "Zoradené podľa vzdialenosti",
12497
12578
  "address_lookup_fail": "Adresa sa nenašla. Skúste to znova prosím.",
12579
+ "favorites": "Obľúbené",
12580
+ "widen search": "Rozšíriť vyhľadávanie",
12581
+ "cancel search": "Zrušiť vyhľadávanie",
12498
12582
  },
12499
12583
  "sv-SE": {
12500
12584
  "days_of_the_week": ["", "Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"],
@@ -12540,6 +12624,7 @@ function CroutonLocalization(language) {
12540
12624
  'all': 'All',
12541
12625
  'menu': "Menu",
12542
12626
  'search for meetings': 'Search for meetings',
12627
+ 'search by location': 'Search by Location',
12543
12628
  'show meetings near...': 'Show meetings near...',
12544
12629
  'filter meetings': 'Filter meetings',
12545
12630
  'visible meeting list': 'Visible meetings as list',
@@ -12668,6 +12753,9 @@ function CroutonHandlebarsExtensions() {
12668
12753
  ? options.fn(this)
12669
12754
  : options.inverse(this);
12670
12755
  });
12756
+ crouton_Handlebars.registerHelper('format_list_style', function(data, options) {
12757
+ return crouton.config.format_list_style === 'formatNames' ? 'formatNames' : 'formatKeys'
12758
+ });
12671
12759
  crouton_Handlebars.registerHelper('groupsConfigured', function(data, options) {
12672
12760
  if (crouton.config.groups) {
12673
12761
  return getTrueResult(options, this);
@@ -12679,8 +12767,8 @@ function CroutonHandlebarsExtensions() {
12679
12767
  * @deprecated Since version 3.12.2, will be removed in a future version.
12680
12768
  */
12681
12769
  crouton_Handlebars.registerHelper('isVirtual', function(data, options) {
12682
- return ((data['venue_type'] === venueType.HYBRID || data['venue_type'] === venueType.VIRTUAL) || ((inArray(getMasterFormatId('HY', data), getFormats(data)) && !inArray(getMasterFormatId('TC', data), getFormats(data)))
12683
- || inArray(getMasterFormatId('VM', data), getFormats(data))))
12770
+ return ((data['venue_type'] === venueType.HYBRID || data['venue_type'] === venueType.VIRTUAL) || ((getFormats(data).includes(getMasterFormatId('HY', data)) && !getFormats(data).includes(getMasterFormatId('TC', data)))
12771
+ || getFormats(data).includes(getMasterFormatId('VM', data))))
12684
12772
  && (data['virtual_meeting_link'] || data['phone_meeting_number'] || data['virtual_meeting_additional_info']) ? getTrueResult(options, this) : getFalseResult(options, this);
12685
12773
  });
12686
12774
 
@@ -12688,83 +12776,85 @@ function CroutonHandlebarsExtensions() {
12688
12776
  * Assumes consistent set of venue type formats (enforced for newly edited meetings in root server 2.16.0 or greater)
12689
12777
  */
12690
12778
  crouton_Handlebars.registerHelper('isVirtualOnly', function(data, options) {
12691
- return data['venue_type'] === venueType.VIRTUAL || inArray(getMasterFormatId('VM', data), getFormats(data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12779
+ return data['venue_type'] === venueType.VIRTUAL || getFormats(data).includes(getMasterFormatId('VM', data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12692
12780
  });
12693
12781
 
12694
12782
  /**
12695
12783
  * @deprecated Since version 3.12.2 will be removed in a future version.
12696
12784
  */
12697
12785
  crouton_Handlebars.registerHelper('isHybrid', function(data, options) {
12698
- return data['venue_type'] === venueType.HYBRID || inArray(getMasterFormatId('HY', data), getFormats(data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12786
+ return data['venue_type'] === venueType.HYBRID || getFormats(data).includes(getMasterFormatId('HY', data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12699
12787
  });
12700
12788
 
12701
12789
  /**
12702
12790
  * Assumes consistent set of venue type formats (enforced for newly edited meetings in root server 2.16.0 or greater)
12703
12791
  */
12704
12792
  crouton_Handlebars.registerHelper('isHybridOnly', function(data, options) {
12705
- return data['venue_type'] === venueType.HYBRID || inArray(getMasterFormatId('HY', data), getFormats(data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12793
+ return data['venue_type'] === venueType.HYBRID || getFormats(data).includes(getMasterFormatId('HY', data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12706
12794
  });
12707
12795
 
12708
12796
  crouton_Handlebars.registerHelper('isTemporarilyClosed', function(data, options) {
12709
- return inArray(getMasterFormatId('TC', data), getFormats(data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12797
+ return getFormats(data).includes(getMasterFormatId('TC', data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12710
12798
  });
12711
12799
 
12712
12800
  crouton_Handlebars.registerHelper('isNotTemporarilyClosed', function(data, options) {
12713
- return !inArray(getMasterFormatId('TC', data), getFormats(data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12801
+ return !getFormats(data).includes(getMasterFormatId('TC', data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12714
12802
  });
12715
12803
 
12716
12804
  /**
12717
12805
  * Assumes consistent set of venue type formats (enforced for newly edited meetings in root server 2.16.0 or greater)
12718
12806
  */
12719
12807
  crouton_Handlebars.registerHelper('isInPersonOrHybrid', function(data, options) {
12720
- return data['venue_type'] !== venueType.VIRTUAL && !inArray(getMasterFormatId('VM', data), getFormats(data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12808
+ return data['venue_type'] !== venueType.VIRTUAL && !getFormats(data).includes(getMasterFormatId('VM', data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12721
12809
  });
12722
12810
 
12723
12811
  /**
12724
12812
  * Assumes consistent set of venue type formats (enforced for newly edited meetings in root server 2.16.0 or greater)
12725
12813
  */
12726
12814
  crouton_Handlebars.registerHelper('isInPersonOnly', function(data, options) {
12727
- return data['venue_type'] === venueType.IN_PERSON || (!inArray(getMasterFormatId('VM', data), getFormats(data))
12728
- && !inArray(getMasterFormatId('HY', data), getFormats(data))) ? getTrueResult(options, this) : getFalseResult(options, this);
12815
+ return data['venue_type'] === venueType.IN_PERSON || (!getFormats(data).includes(getMasterFormatId('VM', data))
12816
+ && !getFormats(data).includes(getMasterFormatId('HY', data))) ? getTrueResult(options, this) : getFalseResult(options, this);
12729
12817
  });
12730
12818
 
12731
12819
  /**
12732
12820
  * Assumes consistent set of venue type formats (enforced for newly edited meetings in root server 2.16.0 or greater)
12733
12821
  */
12734
12822
  crouton_Handlebars.registerHelper('isVirtualOrHybrid', function(data, options) {
12735
- return (data['venue_type'] === venueType.VIRTUAL || data['venue_type'] === venueType.HYBRID) || inArray(getMasterFormatId('VM', data), getFormats(data))
12736
- || inArray(getMasterFormatId('HY', data), getFormats(data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12823
+ return (data['venue_type'] === venueType.VIRTUAL || data['venue_type'] === venueType.HYBRID) || getFormats(data).includes(getMasterFormatId('VM', data))
12824
+ || getFormats(data).includes(getMasterFormatId('HY', data)) ? getTrueResult(options, this) : getFalseResult(options, this);
12737
12825
  });
12738
12826
 
12739
12827
  crouton_Handlebars.registerHelper('hasFormats', function(formats, data, options) {
12740
- var allFound = false;
12741
- var formatsResponse = data['formats'].split(",")
12742
- var formatsParam = formats.split(",");
12828
+ const formatsResponse = data['formats'].split(",")
12829
+ const formatsParam = formats.split(",");
12743
12830
  for(var i = 0;i < formatsParam.length;i++) {
12744
- allFound = inArray(formatsParam[i], formatsResponse);
12831
+ if (!formatsResponse.includes(formatsParam[i]))
12832
+ return getFalseResult(options, this);
12745
12833
  }
12746
-
12747
- return allFound ? getTrueResult(options, this) : getFalseResult(options, this);
12834
+ return getTrueResult(options, this);
12748
12835
  });
12749
12836
  crouton_Handlebars.registerHelper('temporarilyClosed', function(data, options) {
12750
- if(data['formats_expanded'].getArrayItemByObjectKeyValue('id', getMasterFormatId('TC', data)) !== undefined) {
12751
- return data['formats_expanded'].getArrayItemByObjectKeyValue('id', getMasterFormatId('TC', data))['description'];
12837
+ const found = data['formats_expanded'].find((format)=>format['id'] === getMasterFormatId('TC', data));
12838
+ if (found !== undefined) {
12839
+ return found['description'];
12752
12840
  } else {
12753
12841
  return crouton.localization.getWord("FACILITY IS TEMPORARILY CLOSED");
12754
12842
  }
12755
12843
  });
12756
12844
 
12757
12845
  crouton_Handlebars.registerHelper('meetsVirtually', function(data, options) {
12758
- if(data['formats_expanded'].getArrayItemByObjectKeyValue('id', getMasterFormatId('VM', data)) !== undefined) {
12759
- return data['formats_expanded'].getArrayItemByObjectKeyValue('id', getMasterFormatId('VM', data))['description'];
12846
+ const found = data['formats_expanded'].find((format)=>format['id'] === getMasterFormatId('VM', data));
12847
+ if (found !== undefined) {
12848
+ return found['description'];
12760
12849
  } else {
12761
12850
  return crouton.localization.getWord("MEETS VIRTUALLY");
12762
12851
  }
12763
12852
  });
12764
12853
 
12765
12854
  crouton_Handlebars.registerHelper('meetsHybrid', function(data, options) {
12766
- if(data['formats_expanded'].getArrayItemByObjectKeyValue('id', getMasterFormatId('HY', data)) !== undefined) {
12767
- return data['formats_expanded'].getArrayItemByObjectKeyValue('id', getMasterFormatId('HY', data))['description'];
12855
+ const found = data['formats_expanded'].find((format)=>format['id'] === getMasterFormatId('HY', data));
12856
+ if (found !== undefined) {
12857
+ return found['description'];
12768
12858
  } else {
12769
12859
  return crouton.localization.getWord("MEETS VIRTUALLY AND IN PERSON");
12770
12860
  }
@@ -12815,6 +12905,18 @@ function CroutonHandlebarsExtensions() {
12815
12905
  return new crouton_Handlebars.SafeString("<a href='tel:" + text + "' target='_blank'>" + text + "</a>");
12816
12906
  });
12817
12907
 
12908
+ function isFavorite(meeting) {
12909
+ const localStorageKey = "crouton-favorites";
12910
+ const favorites = JSON.parse(localStorage.getItem(localStorageKey) || "[]");
12911
+ return favorites.includes(meeting.root_server_uri + "_" + meeting.id_bigint);
12912
+ }
12913
+ crouton_Handlebars.registerHelper('favoriteIcon', function(meeting, options) {
12914
+ return new crouton_Handlebars.SafeString("<span id='crouton-favorite-" + meeting.id_bigint + "' class='crouton-favorite glyphicon glyphicon-heart" + (!isFavorite(meeting) ? "-empty" : "") + "'></span>");
12915
+ });
12916
+
12917
+ crouton_Handlebars.registerHelper('isFavorite', function(meeting, options) {
12918
+ return new crouton_Handlebars.SafeString(isFavorite(meeting) ? 1 : 0);
12919
+ });
12818
12920
  crouton_Handlebars.registerHelper('ifEquals', function(arg1, arg2, options) {
12819
12921
  return (arg1 === arg2) ? options.fn(this) : options.inverse(this);
12820
12922
  });
@@ -12890,8 +12992,31 @@ function CroutonHandlebarsExtensions() {
12890
12992
  <br/>
12891
12993
  {{/if}}
12892
12994
  `);
12995
+ crouton_Handlebars.registerPartial('formatNames', `
12996
+ {{#each formats_expanded}}
12997
+ <a
12998
+ class="bmlt-formats btn btn-primary btn-xs"
12999
+ title=""
13000
+ data-html="true"
13001
+ tabindex="0"
13002
+ data-trigger="focus"
13003
+ role="button"
13004
+ data-toggle="popover"
13005
+ data-original-title=""
13006
+ data-placement="{{{getWord 'bootstrap-popover-placement'}}}"
13007
+ data-content="{{description}}">
13008
+ <span class="glyphicon glyphicon-search"
13009
+ aria-hidden="true"
13010
+ data-toggle="popover"
13011
+ data-trigger="focus"
13012
+ data-html="true"
13013
+ role="button"></span>{{ name }}
13014
+ </a>
13015
+ {{/each}}
13016
+ `
13017
+ )
12893
13018
  crouton_Handlebars.registerPartial('formatKeys', `
12894
- {{#if this.formats}}
13019
+ {{#if this.formats}}
12895
13020
  <a
12896
13021
  class="bmlt-formats btn btn-primary btn-xs"
12897
13022
  title=""
@@ -12913,7 +13038,6 @@ function CroutonHandlebarsExtensions() {
12913
13038
  {{/if}}
12914
13039
  `
12915
13040
  )
12916
-
12917
13041
  crouton_Handlebars.registerPartial('observerLine', `
12918
13042
  {{#if (hasObserverLine name phone email) }}
12919
13043
  <div class='observerLine'>{{getWord "Contact"}}: {{name}} <a href='tel:{{phone}}'>{{phone}}</a> <a href='mailto:{{email}}'>{{email}}</a></div>
@@ -13344,8 +13468,10 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13344
13468
  + ((stack1 = lookupProperty(helpers,"each").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"grouping_buttons") : stack1),{"name":"each","hash":{},"fn":container.program(2, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":6,"column":4},"end":{"line":8,"column":13}}})) != null ? stack1 : "")
13345
13469
  + ((stack1 = lookupProperty(helpers,"each").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"formattype_grouping_buttons") : stack1),{"name":"each","hash":{},"fn":container.program(3, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":9,"column":4},"end":{"line":11,"column":13}}})) != null ? stack1 : "")
13346
13470
  + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"map_page") : stack1),{"name":"if","hash":{},"fn":container.program(4, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":12,"column":4},"end":{"line":14,"column":11}}})) != null ? stack1 : "")
13347
- + "\n"
13348
- + ((stack1 = lookupProperty(helpers,"each").call(alias1,(depth0 != null ? lookupProperty(depth0,"dropdownData") : depth0),{"name":"each","hash":{},"fn":container.program(5, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":16,"column":4},"end":{"line":25,"column":13}}})) != null ? stack1 : "")
13471
+ + " <div class=\"bmlt-button-container\"><a id=\"crouton_favorites_button\" tabindex=0 class=\"croutonControlButton btn btn-primary btn-sm\">"
13472
+ + container.escapeExpression((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(alias1,"Favorites",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":15,"column":135},"end":{"line":15,"column":158}}}))
13473
+ + "</a></div>\n\n"
13474
+ + ((stack1 = lookupProperty(helpers,"each").call(alias1,(depth0 != null ? lookupProperty(depth0,"dropdownData") : depth0),{"name":"each","hash":{},"fn":container.program(5, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":17,"column":4},"end":{"line":26,"column":13}}})) != null ? stack1 : "")
13349
13475
  + " </div>\n";
13350
13476
  },"1":function(container,depth0,helpers,partials,data) {
13351
13477
  var lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13370,8 +13496,8 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13370
13496
  + alias2(alias1((depth0 != null ? lookupProperty(depth0,"field") : depth0), depth0))
13371
13497
  + "\" tabindex=0 data-field=\""
13372
13498
  + alias2(alias1((depth0 != null ? lookupProperty(depth0,"title") : depth0), depth0))
13373
- + "\" class=\"groupingButton groupingButtonLogic btn btn-primary btn-sm\">"
13374
- + alias2((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? lookupProperty(depth0,"title") : depth0),{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":7,"column":186},"end":{"line":7,"column":208}}}))
13499
+ + "\" class=\"groupingButton croutonControlButton groupingButtonLogic btn btn-primary btn-sm\">"
13500
+ + alias2((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? lookupProperty(depth0,"title") : depth0),{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":7,"column":207},"end":{"line":7,"column":229}}}))
13375
13501
  + "</a></div>\n";
13376
13502
  },"3":function(container,depth0,helpers,partials,data) {
13377
13503
  var alias1=container.lambda, alias2=container.escapeExpression, lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13385,7 +13511,7 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13385
13511
  + alias2(alias1((depth0 != null ? lookupProperty(depth0,"field") : depth0), depth0))
13386
13512
  + "\"tabindex=0 data-field=\""
13387
13513
  + alias2(alias1((depth0 != null ? lookupProperty(depth0,"field") : depth0), depth0))
13388
- + "\" class=\"groupingButton groupingButtonLogic btn btn-primary btn-sm\">"
13514
+ + "\" class=\"groupingButton croutonControlButton groupingButtonLogic btn btn-primary btn-sm\">"
13389
13515
  + alias2(alias1((depth0 != null ? lookupProperty(depth0,"title") : depth0), depth0))
13390
13516
  + "</a></div>\n";
13391
13517
  },"4":function(container,depth0,helpers,partials,data) {
@@ -13396,8 +13522,8 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13396
13522
  return undefined
13397
13523
  };
13398
13524
 
13399
- return " <div class=\"bmlt-button-container\"><a id=\"groupingButton_embeddedMapPage\" tabindex=0 data-field=\"embeddedMapPage\" class=\"groupingButton btn btn-primary btn-sm\">"
13400
- + container.escapeExpression((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),"map",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":13,"column":168},"end":{"line":13,"column":185}}}))
13525
+ return " <div class=\"bmlt-button-container\"><a id=\"groupingButton_embeddedMapPage\" tabindex=0 data-field=\"embeddedMapPage\" class=\"groupingButton croutonControlButton btn btn-primary btn-sm\">"
13526
+ + container.escapeExpression((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),"map",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":13,"column":189},"end":{"line":13,"column":206}}}))
13401
13527
  + "</a></div>\n";
13402
13528
  },"5":function(container,depth0,helpers,partials,data,blockParams,depths) {
13403
13529
  var stack1, helper, alias1=container.escapeExpression, alias2=depth0 != null ? depth0 : (container.nullContext || {}), alias3=container.hooks.helperMissing, alias4="function", lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13410,17 +13536,17 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13410
13536
  return " <div class=\"bmlt-dropdown-container\">\n <select class=\"crouton-select filter-dropdown\" style=\"width:"
13411
13537
  + alias1(container.lambda(((stack1 = (depths[1] != null ? lookupProperty(depths[1],"config") : depths[1])) != null ? lookupProperty(stack1,"dropdown_width") : stack1), depth0))
13412
13538
  + ";\" data-placeholder=\""
13413
- + alias1(((helper = (helper = lookupProperty(helpers,"placeholder") || (depth0 != null ? lookupProperty(depth0,"placeholder") : depth0)) != null ? helper : alias3),(typeof helper === alias4 ? helper.call(alias2,{"name":"placeholder","hash":{},"data":data,"loc":{"start":{"line":18,"column":116},"end":{"line":18,"column":131}}}) : helper)))
13539
+ + alias1(((helper = (helper = lookupProperty(helpers,"placeholder") || (depth0 != null ? lookupProperty(depth0,"placeholder") : depth0)) != null ? helper : alias3),(typeof helper === alias4 ? helper.call(alias2,{"name":"placeholder","hash":{},"data":data,"loc":{"start":{"line":19,"column":116},"end":{"line":19,"column":131}}}) : helper)))
13414
13540
  + "\" data-pointer=\""
13415
- + alias1(((helper = (helper = lookupProperty(helpers,"pointer") || (depth0 != null ? lookupProperty(depth0,"pointer") : depth0)) != null ? helper : alias3),(typeof helper === alias4 ? helper.call(alias2,{"name":"pointer","hash":{},"data":data,"loc":{"start":{"line":18,"column":147},"end":{"line":18,"column":158}}}) : helper)))
13541
+ + alias1(((helper = (helper = lookupProperty(helpers,"pointer") || (depth0 != null ? lookupProperty(depth0,"pointer") : depth0)) != null ? helper : alias3),(typeof helper === alias4 ? helper.call(alias2,{"name":"pointer","hash":{},"data":data,"loc":{"start":{"line":19,"column":147},"end":{"line":19,"column":158}}}) : helper)))
13416
13542
  + "\" id="
13417
- + alias1(((helper = (helper = lookupProperty(helpers,"elementId") || (depth0 != null ? lookupProperty(depth0,"elementId") : depth0)) != null ? helper : alias3),(typeof helper === alias4 ? helper.call(alias2,{"name":"elementId","hash":{},"data":data,"loc":{"start":{"line":18,"column":163},"end":{"line":18,"column":176}}}) : helper)))
13543
+ + alias1(((helper = (helper = lookupProperty(helpers,"elementId") || (depth0 != null ? lookupProperty(depth0,"elementId") : depth0)) != null ? helper : alias3),(typeof helper === alias4 ? helper.call(alias2,{"name":"elementId","hash":{},"data":data,"loc":{"start":{"line":19,"column":163},"end":{"line":19,"column":176}}}) : helper)))
13418
13544
  + ">\n <option value=\"a-\">"
13419
- + alias1((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias3).call(alias2,"all",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":19,"column":25},"end":{"line":19,"column":42}}}))
13545
+ + alias1((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias3).call(alias2,"all",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":20,"column":25},"end":{"line":20,"column":42}}}))
13420
13546
  + " "
13421
- + alias1(((helper = (helper = lookupProperty(helpers,"placeholder") || (depth0 != null ? lookupProperty(depth0,"placeholder") : depth0)) != null ? helper : alias3),(typeof helper === alias4 ? helper.call(alias2,{"name":"placeholder","hash":{},"data":data,"loc":{"start":{"line":19,"column":43},"end":{"line":19,"column":58}}}) : helper)))
13547
+ + alias1(((helper = (helper = lookupProperty(helpers,"placeholder") || (depth0 != null ? lookupProperty(depth0,"placeholder") : depth0)) != null ? helper : alias3),(typeof helper === alias4 ? helper.call(alias2,{"name":"placeholder","hash":{},"data":data,"loc":{"start":{"line":20,"column":43},"end":{"line":20,"column":58}}}) : helper)))
13422
13548
  + "</option>\n"
13423
- + ((stack1 = lookupProperty(helpers,"each").call(alias2,(lookupProperty(helpers,"call")||(depth0 && lookupProperty(depth0,"call"))||alias3).call(alias2,(depth0 != null ? lookupProperty(depth0,"uniqueData") : depth0),((stack1 = (depths[1] != null ? lookupProperty(depths[1],"meetings") : depths[1])) != null ? lookupProperty(stack1,"meetingData") : stack1),{"name":"call","hash":{},"data":data,"loc":{"start":{"line":20,"column":14},"end":{"line":20,"column":55}}}),{"name":"each","hash":{},"fn":container.program(6, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":20,"column":6},"end":{"line":22,"column":15}}})) != null ? stack1 : "")
13549
+ + ((stack1 = lookupProperty(helpers,"each").call(alias2,(lookupProperty(helpers,"call")||(depth0 && lookupProperty(depth0,"call"))||alias3).call(alias2,(depth0 != null ? lookupProperty(depth0,"uniqueData") : depth0),((stack1 = (depths[1] != null ? lookupProperty(depths[1],"meetings") : depths[1])) != null ? lookupProperty(stack1,"meetingData") : stack1),{"name":"call","hash":{},"data":data,"loc":{"start":{"line":21,"column":14},"end":{"line":21,"column":55}}}),{"name":"each","hash":{},"fn":container.program(6, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":21,"column":6},"end":{"line":23,"column":15}}})) != null ? stack1 : "")
13424
13550
  + " </select>\n </div>\n";
13425
13551
  },"6":function(container,depth0,helpers,partials,data,blockParams,depths) {
13426
13552
  var alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=container.hooks.helperMissing, alias3=container.escapeExpression, lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13431,9 +13557,9 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13431
13557
  };
13432
13558
 
13433
13559
  return " <option value=\"a-"
13434
- + alias3((lookupProperty(helpers,"call")||(depth0 && lookupProperty(depth0,"call"))||alias2).call(alias1,(depths[1] != null ? lookupProperty(depths[1],"objectPointer") : depths[1]),depth0,{"name":"call","hash":{},"data":data,"loc":{"start":{"line":21,"column":24},"end":{"line":21,"column":54}}}))
13560
+ + alias3((lookupProperty(helpers,"call")||(depth0 && lookupProperty(depth0,"call"))||alias2).call(alias1,(depths[1] != null ? lookupProperty(depths[1],"objectPointer") : depths[1]),depth0,{"name":"call","hash":{},"data":data,"loc":{"start":{"line":22,"column":24},"end":{"line":22,"column":54}}}))
13435
13561
  + "\">"
13436
- + alias3((lookupProperty(helpers,"call")||(depth0 && lookupProperty(depth0,"call"))||alias2).call(alias1,(depths[1] != null ? lookupProperty(depths[1],"optionName") : depths[1]),depth0,{"name":"call","hash":{},"data":data,"loc":{"start":{"line":21,"column":56},"end":{"line":21,"column":83}}}))
13562
+ + alias3((lookupProperty(helpers,"call")||(depth0 && lookupProperty(depth0,"call"))||alias2).call(alias1,(depths[1] != null ? lookupProperty(depths[1],"optionName") : depths[1]),depth0,{"name":"call","hash":{},"data":data,"loc":{"start":{"line":22,"column":56},"end":{"line":22,"column":83}}}))
13437
13563
  + "</option>\n";
13438
13564
  },"7":function(container,depth0,helpers,partials,data) {
13439
13565
  var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {}), lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13443,9 +13569,9 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13443
13569
  return undefined
13444
13570
  };
13445
13571
 
13446
- return ((stack1 = (lookupProperty(helpers,"ifEquals")||(depth0 && lookupProperty(depth0,"ifEquals"))||container.hooks.helperMissing).call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"view_by") : stack1),"weekdays",{"name":"ifEquals","hash":{},"fn":container.program(8, data, 0),"inverse":container.program(9, data, 0),"data":data,"loc":{"start":{"line":30,"column":4},"end":{"line":34,"column":17}}})) != null ? stack1 : "")
13572
+ return ((stack1 = (lookupProperty(helpers,"ifEquals")||(depth0 && lookupProperty(depth0,"ifEquals"))||container.hooks.helperMissing).call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"view_by") : stack1),"weekdays",{"name":"ifEquals","hash":{},"fn":container.program(8, data, 0),"inverse":container.program(9, data, 0),"data":data,"loc":{"start":{"line":31,"column":4},"end":{"line":35,"column":17}}})) != null ? stack1 : "")
13447
13573
  + " <ul class=\"nav nav-tabs\">\n"
13448
- + ((stack1 = lookupProperty(helpers,"each").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"day_sequence") : stack1),{"name":"each","hash":{},"fn":container.program(10, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":36,"column":12},"end":{"line":38,"column":21}}})) != null ? stack1 : "")
13574
+ + ((stack1 = lookupProperty(helpers,"each").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"day_sequence") : stack1),{"name":"each","hash":{},"fn":container.program(10, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":37,"column":12},"end":{"line":39,"column":21}}})) != null ? stack1 : "")
13449
13575
  + " </ul>\n </div>\n";
13450
13576
  },"8":function(container,depth0,helpers,partials,data) {
13451
13577
  var lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13456,7 +13582,7 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13456
13582
  };
13457
13583
 
13458
13584
  return " <div class=\"bmlt-page "
13459
- + container.escapeExpression((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),"css-direction",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":31,"column":30},"end":{"line":31,"column":57}}}))
13585
+ + container.escapeExpression((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),"css-direction",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":32,"column":30},"end":{"line":32,"column":57}}}))
13460
13586
  + " show\" id=\"nav-days\">\n";
13461
13587
  },"9":function(container,depth0,helpers,partials,data) {
13462
13588
  var lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13467,7 +13593,7 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13467
13593
  };
13468
13594
 
13469
13595
  return " <div class=\"bmlt-page "
13470
- + container.escapeExpression((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),"css-direction",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":33,"column":30},"end":{"line":33,"column":57}}}))
13596
+ + container.escapeExpression((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),"css-direction",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":34,"column":30},"end":{"line":34,"column":57}}}))
13471
13597
  + " hide\" id=\"nav-days\">\n";
13472
13598
  },"10":function(container,depth0,helpers,partials,data) {
13473
13599
  var alias1=container.escapeExpression, lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13480,7 +13606,7 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13480
13606
  return " <li><a href=\"#tab"
13481
13607
  + alias1(container.lambda(depth0, depth0))
13482
13608
  + "\" data-toggle=\"tab\">"
13483
- + alias1((lookupProperty(helpers,"getDayOfTheWeek")||(depth0 && lookupProperty(depth0,"getDayOfTheWeek"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),depth0,{"name":"getDayOfTheWeek","hash":{},"data":data,"loc":{"start":{"line":37,"column":61},"end":{"line":37,"column":85}}}))
13609
+ + alias1((lookupProperty(helpers,"getDayOfTheWeek")||(depth0 && lookupProperty(depth0,"getDayOfTheWeek"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),depth0,{"name":"getDayOfTheWeek","hash":{},"data":data,"loc":{"start":{"line":38,"column":61},"end":{"line":38,"column":85}}}))
13484
13610
  + "</a></li>\n";
13485
13611
  },"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) {
13486
13612
  var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {}), lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13492,10 +13618,38 @@ this["hbs_Crouton"]["templates"]["header"] = Handlebars.template({"0":function(c
13492
13618
 
13493
13619
  return container.escapeExpression((lookupProperty(helpers,"startup")||(depth0 && lookupProperty(depth0,"startup"))||container.hooks.helperMissing).call(alias1,depth0,{"name":"startup","hash":{},"data":data,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}}}))
13494
13620
  + "\n"
13495
- + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"header") : stack1),{"name":"if","hash":{},"fn":container.program(0, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":2,"column":0},"end":{"line":27,"column":7}}})) != null ? stack1 : "")
13621
+ + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"header") : stack1),{"name":"if","hash":{},"fn":container.program(0, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":2,"column":0},"end":{"line":28,"column":7}}})) != null ? stack1 : "")
13496
13622
  + "\n"
13497
- + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"has_tabs") : stack1),{"name":"if","hash":{},"fn":container.program(7, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":29,"column":0},"end":{"line":41,"column":7}}})) != null ? stack1 : "");
13623
+ + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"config") : depth0)) != null ? lookupProperty(stack1,"has_tabs") : stack1),{"name":"if","hash":{},"fn":container.program(7, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":30,"column":0},"end":{"line":42,"column":7}}})) != null ? stack1 : "");
13498
13624
  },"useData":true,"useDepths":true});
13625
+ this["hbs_Crouton"]["templates"]["locationSearch"] = Handlebars.template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
13626
+ var alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=container.hooks.helperMissing, alias3=container.escapeExpression, lookupProperty = container.lookupProperty || function(parent, propertyName) {
13627
+ if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
13628
+ return parent[propertyName];
13629
+ }
13630
+ return undefined
13631
+ };
13632
+
13633
+ return "<button id=\"location-search-button\" style=\"width: auto\" class=\"location-search-button\" title=\""
13634
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Open Location Search Dialog",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":1,"column":94},"end":{"line":1,"column":135}}}))
13635
+ + "\">\n <span class=\"location-search-button-label\" style=\"position:initial;\">\n "
13636
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Search by location",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":3,"column":8},"end":{"line":3,"column":40}}}))
13637
+ + "\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"currentColor\" class=\"bi bi-crosshair\" viewBox=\"0 0 16 16\" style=\"vertical-align: sub;\">\n <path d=\"M8.5.5a.5.5 0 0 0-1 0v.518A7 7 0 0 0 1.018 7.5H.5a.5.5 0 0 0 0 1h.518A7 7 0 0 0 7.5 14.982v.518a.5.5 0 0 0 1 0v-.518A7 7 0 0 0 14.982 8.5h.518a.5.5 0 0 0 0-1h-.518A7 7 0 0 0 8.5 1.018zm-6.48 7A6 6 0 0 1 7.5 2.02v.48a.5.5 0 0 0 1 0v-.48a6 6 0 0 1 5.48 5.48h-.48a.5.5 0 0 0 0 1h.48a6 6 0 0 1-5.48 5.48v-.48a.5.5 0 0 0-1 0v.48A6 6 0 0 1 2.02 8.5h.48a.5.5 0 0 0 0-1zM8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4\"/>\n </svg>\n </span>\n</button>\n<div id=\"bmlt_location_search_modal\" class=\"modal\" style=\"display: none;\">\n <div id=\"bmlt_location_search_content\" class=\"modal-content\" style=\"border-color:unset;\">\n <span id=\"close_location_search\" class=\"modal-close\">x</span>\n <div class=\"modal-title\">"
13638
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Search by location",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":12,"column":33},"end":{"line":12,"column":65}}}))
13639
+ + "</div>\n <div class=\"crouton-modal-search-page\">\n <div id=\"modal-location-search-box\" class=\"modal-search\">\n <input id=\"bmlt-location-search-goto-text\" type=\"text\" class=\"crouton-goto-text\"\n placeholder=\""
13640
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Enter a city or zip code",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":16,"column":33},"end":{"line":16,"column":71}}}))
13641
+ + "\">\n <button id=\"bmlt-location-search-text-button\" class=\"filter-button\">"
13642
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"text_search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":17,"column":84},"end":{"line":17,"column":109}}}))
13643
+ + "</button>\n </div>\n <div class=\"modal-search\">\n <button id=\"bmlt-location-search-nearbyMeetings\" class=\"filter-button\">"
13644
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"near_me",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":20,"column":87},"end":{"line":20,"column":108}}}))
13645
+ + "</button>\n </div>\n <div id=\"location-search-widen\" class=\"modal-search\">\n <button id=\"bmlt-location-search-widen\" class=\"filter-button\">"
13646
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Widen Search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":23,"column":78},"end":{"line":23,"column":104}}}))
13647
+ + "</button>\n </div>\n <div>\n <!--<button id=\"location-search-close\" class=\"advanced-search-button\" style=\"float:left\">"
13648
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Close",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":26,"column":96},"end":{"line":26,"column":115}}}))
13649
+ + "</a>-->\n <button id=\"bmlt-location_search-cancel\" class=\"advanced-search-button\">"
13650
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Cancel Search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":27,"column":88},"end":{"line":27,"column":115}}}))
13651
+ + "</button>\n </div>\n </div>\n <div class=\"crouton-modal-search-choice\"></div>\n </div>\n</div>";
13652
+ },"useData":true});
13499
13653
  this["hbs_Crouton"]["templates"]["main"] = Handlebars.template({"0":function(container,depth0,helpers,partials,data) {
13500
13654
  var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=container.hooks.helperMissing, alias3=container.escapeExpression, lookupProperty = container.lookupProperty || function(parent, propertyName) {
13501
13655
  if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
@@ -13692,11 +13846,11 @@ this["hbs_Crouton"]["templates"]["mapMenu"] = Handlebars.template({"0":function(
13692
13846
  + ((stack1 = lookupProperty(helpers,"each").call(alias2,((stack1 = (depth0 != null ? lookupProperty(depth0,"meetings") : depth0)) != null ? lookupProperty(stack1,"bydays") : stack1),{"name":"each","hash":{},"fn":container.program(4, data, 0, blockParams, depths),"inverse":container.noop,"data":data,"loc":{"start":{"line":36,"column":8},"end":{"line":38,"column":17}}})) != null ? stack1 : "")
13693
13847
  + " </table>\n </div>\n</div>\n<div id=\"geocoding_modal\" class=\"modal\" style=\"display: none;\">\n <div id=\"search_content\" class=\"modal-content\">\n <span class=\"modal-title\">"
13694
13848
  + alias1((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias3).call(alias2,"Show meetings near...",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":44,"column":28},"end":{"line":44,"column":63}}}))
13695
- + "</span><span id=\"close_search\" class=\"modal-close\">x</span>\n <p></p>\n <div class=\"modal-search\">\n "
13696
- + alias1((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias3).call(alias2,"Enter a city or zip code",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":47,"column":12},"end":{"line":47,"column":50}}}))
13697
- + "\n <input id=\"goto-text\" type=\"text\">\n <button id=\"goto-button\" class=\"filter-button\">"
13698
- + alias1((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias3).call(alias2,"go",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":49,"column":59},"end":{"line":49,"column":75}}}))
13699
- + "</button>\n </div>\n </div>\n</div>\n\n";
13849
+ + "</span><span id=\"close_search\" class=\"modal-close\">x</span>\n <p></p>\n <div class=\"crouton-modal-search-page\">\n <div class=\"modal-search\">\n "
13850
+ + alias1((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias3).call(alias2,"Enter a city or zip code",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":48,"column":16},"end":{"line":48,"column":54}}}))
13851
+ + "\n <input id=\"goto-text\" class=\"crouton-goto-text\" type=\"text\">\n <button id=\"goto-button\" class=\"filter-button\">"
13852
+ + alias1((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias3).call(alias2,"text_search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":50,"column":63},"end":{"line":50,"column":88}}}))
13853
+ + "</button>\n </div>\n </div>\n <div class=\"crouton-modal-search-choice\"></div>\n </div>\n</div>\n\n";
13700
13854
  },"usePartial":true,"useData":true,"useDepths":true});
13701
13855
  this["hbs_Crouton"]["templates"]["mapSearch"] = Handlebars.template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
13702
13856
  var alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=container.hooks.helperMissing, alias3=container.escapeExpression, lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -13710,13 +13864,13 @@ this["hbs_Crouton"]["templates"]["mapSearch"] = Handlebars.template({"compiler":
13710
13864
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Open Search Dialog",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":1,"column":58},"end":{"line":1,"column":90}}}))
13711
13865
  + "\">\n <span class=\"menu-button-label\" style=\"position:initial;\">"
13712
13866
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Search for meetings",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":2,"column":62},"end":{"line":2,"column":95}}}))
13713
- + "</span>\n</button>\n<div id=\"bmltsearch_modal\" class=\"modal\" style=\"display: none;\">\n <div id=\"bmltsearch_content\" class=\"modal-content\">\n <span id=\"close_search\" class=\"modal-close\">x</span>\n <div id=\"modal-search-page\">\n <div class=\"modal-title\">"
13867
+ + "</span>\n</button>\n<div id=\"bmltsearch_modal\" class=\"modal\" style=\"display: none;\">\n <div id=\"bmltsearch_content\" class=\"modal-content\">\n <span id=\"close_search\" class=\"modal-close\">x</span>\n <div class=\"crouton-modal-search-page\">\n <div class=\"modal-title\">"
13714
13868
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Search for meetings",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":8,"column":37},"end":{"line":8,"column":70}}}))
13715
13869
  + "</div>\n <div id=\"zoomed-out-message\" class=\"hide\">\n <p>"
13716
13870
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"zoomed-out-message",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":10,"column":19},"end":{"line":10,"column":51}}}))
13717
13871
  + "</p>\n </div>\n <div id=\"modal-search-box\" class=\"modal-search\">\n <input id=\"bmltsearch-goto-text\" type=\"text\"\n placeholder=\""
13718
13872
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Enter a city or zip code",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":14,"column":33},"end":{"line":14,"column":71}}}))
13719
- + "\" style=\"margin-bottom:5px;\">\n <button id=\"bmltsearch-text-button\" class=\"filter-button\">"
13873
+ + "\" class=\"crouton-goto-text\">\n <button id=\"bmltsearch-text-button\" class=\"filter-button\">"
13720
13874
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"text_search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":15,"column":74},"end":{"line":15,"column":99}}}))
13721
13875
  + "</button>\n </div>\n <div class=\"modal-search\">\n <button id=\"bmltsearch-nearbyMeetings\" class=\"filter-button\">"
13722
13876
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"near_me",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":18,"column":77},"end":{"line":18,"column":98}}}))
@@ -13724,14 +13878,14 @@ this["hbs_Crouton"]["templates"]["mapSearch"] = Handlebars.template({"compiler":
13724
13878
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"click_search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":21,"column":74},"end":{"line":21,"column":100}}}))
13725
13879
  + "</button>\n </div>\n <button id=\"show-search-parameters\" class=\"advanced-search-button\">"
13726
13880
  + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Adjust Search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":23,"column":79},"end":{"line":23,"column":106}}}))
13727
- + "</button>\n </div>\n <div id=\"modal-seach-parameters\">\n <div class=\"modal-title\">"
13728
- + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Adjust Search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":26,"column":37},"end":{"line":26,"column":64}}}))
13881
+ + "</button>\n </div>\n <div class=\"crouton-modal-search-choice\"></div>\n <div id=\"modal-seach-parameters\">\n <div class=\"modal-title\">"
13882
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Adjust Search",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":27,"column":37},"end":{"line":27,"column":64}}}))
13729
13883
  + "</div>\n <input type=\"number\" id=\"search_parameter\" name=\"search_parameter\" maxlength=\"3\" size=\"3\">\n <p>"
13730
- + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"This number represents",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":28,"column":15},"end":{"line":28,"column":51}}}))
13884
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"This number represents",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":29,"column":15},"end":{"line":29,"column":51}}}))
13731
13885
  + ":</p>\n <input type=\"radio\" id=\"search_radius\" name=\"map_search_type\" value=\"radius\">\n <label id=\"search_radius_label\" for=\"search_radius\"></label><br>\n <input type=\"radio\" id=\"search_count\" name=\"map_search_type\" value=\"count\">\n <label for=\"search_count\">"
13732
- + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Approx. number of meetings in result",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":32,"column":38},"end":{"line":32,"column":88}}}))
13886
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Approx. number of meetings in result",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":33,"column":38},"end":{"line":33,"column":88}}}))
13733
13887
  + "</label><br>\n <button id=\"show-search-page\" class=\"advanced-search-button\">"
13734
- + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Back",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":33,"column":73},"end":{"line":33,"column":91}}}))
13888
+ + alias3((lookupProperty(helpers,"getWord")||(depth0 && lookupProperty(depth0,"getWord"))||alias2).call(alias1,"Back",{"name":"getWord","hash":{},"data":data,"loc":{"start":{"line":34,"column":73},"end":{"line":34,"column":91}}}))
13735
13889
  + "</button>\n </div>\n </div>\n</div>";
13736
13890
  },"useData":true});
13737
13891
  this["hbs_Crouton"]["templates"]["meeting3ColumnRow"] = Handlebars.template({"0":function(container,depth0,helpers,partials,data) {
@@ -14038,7 +14192,9 @@ this["hbs_Crouton"]["templates"]["tableRows"] = Handlebars.template({"0":functio
14038
14192
  + alias3((lookupProperty(helpers,"formatDataFromArray")||(depth0 && lookupProperty(depth0,"formatDataFromArray"))||alias2).call(alias1,(depth0 != null ? lookupProperty(depth0,"venue_type_name") : depth0),{"name":"formatDataFromArray","hash":{},"data":data,"loc":{"start":{"line":15,"column":15},"end":{"line":15,"column":59}}}))
14039
14193
  + "\"\n data-weekdays=\""
14040
14194
  + alias3((lookupProperty(helpers,"formatDataPointer")||(depth0 && lookupProperty(depth0,"formatDataPointer"))||alias2).call(alias1,(depth0 != null ? lookupProperty(depth0,"formatted_day") : depth0),{"name":"formatDataPointer","hash":{},"data":data,"loc":{"start":{"line":16,"column":17},"end":{"line":16,"column":57}}}))
14041
- + "\">\n"
14195
+ + "\"\n data-favorite="
14196
+ + alias3((lookupProperty(helpers,"isFavorite")||(depth0 && lookupProperty(depth0,"isFavorite"))||alias2).call(alias1,depth0,{"name":"isFavorite","hash":{},"data":data,"loc":{"start":{"line":17,"column":16},"end":{"line":17,"column":35}}}))
14197
+ + ">\n"
14042
14198
  + ((stack1 = container.invokePartial(lookupProperty(partials,"tableDataRow"),depth0,{"name":"tableDataRow","data":data,"indent":"\t\t","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
14043
14199
  + " </tr>\n";
14044
14200
  },"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
@@ -14049,7 +14205,7 @@ this["hbs_Crouton"]["templates"]["tableRows"] = Handlebars.template({"0":functio
14049
14205
  return undefined
14050
14206
  };
14051
14207
 
14052
- return ((stack1 = lookupProperty(helpers,"each").call(depth0 != null ? depth0 : (container.nullContext || {}),depth0,{"name":"each","hash":{},"fn":container.program(0, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":1,"column":0},"end":{"line":19,"column":9}}})) != null ? stack1 : "");
14208
+ return ((stack1 = lookupProperty(helpers,"each").call(depth0 != null ? depth0 : (container.nullContext || {}),depth0,{"name":"each","hash":{},"fn":container.program(0, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":1,"column":0},"end":{"line":20,"column":9}}})) != null ? stack1 : "");
14053
14209
  },"usePartial":true,"useData":true});
14054
14210
  this["hbs_Crouton"]["templates"]["weekdays"] = Handlebars.template({"0":function(container,depth0,helpers,partials,data) {
14055
14211
  var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=container.hooks.helperMissing, alias3=container.escapeExpression, lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -14175,13 +14331,16 @@ var croutonDefaultTemplates = {
14175
14331
  </div>
14176
14332
  `,
14177
14333
  meeting_times_template: `
14178
- <div class="bmlt-day">{{this.formatted_day}}</div>
14334
+ <div class="bmlt-meeting-day-favorite">
14335
+ <div class="bmlt-day">{{this.formatted_day}}</div>
14336
+ <div class="favorite-icon">{{favoriteIcon this}}</div>
14337
+ </div>
14179
14338
  {{#ifEquals this.duration_time "24:00:00"}}
14180
14339
  <div class="bmlt-time-2">{{this.start_time_formatted}}</div>
14181
14340
  {{else}}
14182
14341
  <div class="bmlt-time-2">{{this.start_time_formatted}} - {{this.end_time_formatted}}</div>
14183
14342
  {{/ifEquals}}
14184
- {{> formatKeys }}
14343
+ {{> (format_list_style) }}
14185
14344
  <div class="bmlt-comments">{{formatLink this.formatted_comments}}</div>
14186
14345
  <div class="bmlt-observer">{{> (selectObserver) }}</div>
14187
14346
  `,
@@ -15277,16 +15436,20 @@ crouton_Handlebars.registerHelper("log", (x) => console.log(x));
15277
15436
  crouton_Handlebars.registerHelper('selectFormatPopup', () => "formatPopup");
15278
15437
  crouton_Handlebars.registerHelper('selectObserver', () => "observerTemplate");
15279
15438
 
15280
-
15439
+ /**
15440
+ * There must be exactly one crouton instance per page.
15441
+ * @param {*} config
15442
+ */
15281
15443
  function Crouton(config) {
15282
- var self = this;
15283
- self.mutex = false;
15444
+ const self = this;
15445
+ self.ready = false;
15284
15446
  self.filtering = false;
15285
15447
  self.masterFormatCodes = [];
15286
15448
  self.currentView = "weekday";
15287
15449
  self.distanceTabAllowed = false;
15450
+ self.favoritesOn = false;
15288
15451
  self.config = {
15289
- version: '4.1.11', // CroutonJS version for debugging
15452
+ version: '4.3.1', // CroutonJS version for debugging
15290
15453
  on_complete: null, // Javascript function to callback when data querying is completed.
15291
15454
  root_server: null, // The root server to use.
15292
15455
  placeholder_id: "bmlt-tabs", // The DOM id that will be used for rendering
@@ -15321,6 +15484,8 @@ function Crouton(config) {
15321
15484
  has_languages: false, // Shows the language dropdown
15322
15485
  has_common_needs: false, // Shows the Common Needs dropdown
15323
15486
  has_venues: true, // Shows the venue types dropdown
15487
+ has_favorites: false, // Shows the favorites button
15488
+ has_geolocation: false, // Shows the geolocation button in the table header
15324
15489
  has_meeting_count: false, // Shows the meeting count
15325
15490
  recurse_service_bodies: false,// Recurses service bodies when making service bodies request
15326
15491
  service_body: [], // Array of service bodies to return data for.
@@ -15363,7 +15528,6 @@ function Crouton(config) {
15363
15528
  tileUrl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
15364
15529
  tileOptions: {
15365
15530
  attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
15366
- maxZoom: 18
15367
15531
  },
15368
15532
  minZoom: 6,
15369
15533
  maxZoom: 17,
@@ -15373,9 +15537,41 @@ function Crouton(config) {
15373
15537
  caption: false,
15374
15538
  groups: false,
15375
15539
  details_table: false,
15540
+ focusedMeetingPopupZoomLevel: 14,
15376
15541
  };
15377
15542
 
15378
15543
  self.setConfig(config);
15544
+ const body = jQuery("body");
15545
+ if (self.config['theme'] !== '') {
15546
+ body.append("<div id='custom-css'><link rel='stylesheet' type='text/css' href='" + self.config['template_path'] + '/themes/' + self.config['theme'] + ".css'>");
15547
+ }
15548
+ if (self.config['custom_css'] !== '') {
15549
+ body.append("<div id='custom-css'><style type='text/css'>" + self.config['custom_css'] + "</style></div>");
15550
+ }
15551
+ self.isIOSDevice = function() {
15552
+ if (navigator.userAgentData && navigator.userAgentData.platform) {
15553
+ if (navigator.userAgentData.platform === 'iOS') {
15554
+ return true;
15555
+ }
15556
+ }
15557
+ const userAgent = navigator.userAgent || navigator.vendor || window.opera;
15558
+ const isIOS = /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream;
15559
+ const isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 && !window.MSStream;
15560
+ return isIOS || isIPadOS;
15561
+ }
15562
+
15563
+ self.isAndroidDevice = function() {
15564
+ return /Android/i.test(navigator.userAgent);
15565
+ }
15566
+ self.deviceType = self.isIOSDevice() ? 'ios' : (self.isAndroidDevice() ? 'android' : 'desktop');
15567
+
15568
+ /**
15569
+ * Do the lookups for the [crouton_map] shortcode
15570
+ * @param float latitude
15571
+ * @param float longitude
15572
+ * @param float width search width that will be sent to the server
15573
+ * @param boolean fitBounds
15574
+ */
15379
15575
  Crouton.prototype.searchByCoordinates = function(latitude, longitude, width, fitBounds=true) {
15380
15576
  const original_query = self.config['custom_query'];
15381
15577
  self.config['custom_query'] = (self.config['custom_query'] !== null ? self.config['custom_query'] : "")
@@ -15384,20 +15580,23 @@ function Crouton(config) {
15384
15580
  self.meetingSearch(function() {
15385
15581
  self.config.refresh_map=1;
15386
15582
  self.config.show_map = 1;
15387
- self.reset();
15583
+ jQuery("#" + self.config["placeholder_id"]).html("");
15388
15584
  self.render(false, fitBounds);
15389
15585
  });
15390
15586
  self.config['custom_query'] = original_query;
15391
15587
  };
15392
15588
 
15589
+ /**
15590
+ * Get the meeting list for the [bmlt_tab] shortcode.
15591
+ * @param string url
15592
+ * @param function cb
15593
+ * @returns Promise that returns when the server query finishes.
15594
+ */
15393
15595
  self.getMeetings = function(url,cb=null) {
15394
- var promises = [fetchJsonp(this.config['root_server'] + url).then(function(response) { return response.json(); })];
15596
+ const promises = [fetchJsonp(this.config['root_server'] + url).then(function(response) { return response.json(); })];
15395
15597
 
15396
15598
  if (self.config['extra_meetings'].length > 0) {
15397
- var extra_meetings_query = "";
15398
- for (var i = 0; i < self.config['extra_meetings'].length; i++) {
15399
- extra_meetings_query += "&meeting_ids[]=" + self.config["extra_meetings"][i];
15400
- }
15599
+ const extra_meetings_query = self.config['extra_meetings'].reduce((query,item) => query + "&meeting_ids[]=" + item, '');
15401
15600
  const regex = /&services\[\]=\d+/;
15402
15601
  url = url.replace(regex, '');
15403
15602
  promises.push(fetchJsonp(self.config['root_server'] + url + extra_meetings_query).then(function (response) { return response.json(); }));
@@ -15405,38 +15604,34 @@ function Crouton(config) {
15405
15604
 
15406
15605
  return Promise.all(promises)
15407
15606
  .then(function(data) {
15408
- var mainMeetings = data[0];
15409
- var extraMeetings;
15410
- var jsonMeetings = JSON.stringify(mainMeetings['meetings']);
15411
- if (data.length === 2) {
15412
- extraMeetings = data[1];
15413
- }
15414
- if (jsonMeetings === "{}" || jsonMeetings === "[]") {
15415
- var fullUrl = self.config['root_server'] + url
15607
+ const mainMeetings = data[0];
15608
+ if (mainMeetings['meetings'].length === 0) {
15609
+ const fullUrl = self.config['root_server'] + url
15416
15610
  console.log("Could not find any meetings for the criteria specified with the query <a href=\"" + fullUrl + "\" target=_blank>" + fullUrl + "</a>");
15417
15611
  jQuery('#' + self.config['placeholder_id']).html("No meetings found.");
15418
15612
  self.meetingData = [];
15419
15613
  self.formatsData = [];
15420
- self.mutex = false;
15421
15614
  cb && cb();
15615
+ self.fireReady();
15422
15616
  return;
15423
15617
  }
15618
+ // TODO: is this necessary? why not just add this to the query?
15424
15619
  if (self.config['exclude_zip_codes'].length > 0) {
15425
- mainMeetings['meetings'] = mainMeetings['meetings'].filter(function(m) { return !inArray(m['location_postal_code_1'], self.config['exclude_zip_codes']); } );
15620
+ mainMeetings['meetings'] = mainMeetings['meetings'].filter(function(m) { return !self.config['exclude_zip_codes'].includes(m['location_postal_code_1']); } );
15426
15621
  }
15427
15622
  self.meetingData = mainMeetings['meetings'];
15428
15623
  self.formatsData = mainMeetings['formats'];
15429
- if (extraMeetings) {
15430
- self.meetingData = self.meetingData.concat(extraMeetings['meetings']);
15624
+ // extra meetings
15625
+ if (data.length === 2) {
15626
+ self.meetingData = self.meetingData.concat(data[1]['meetings']);
15431
15627
  }
15432
15628
  cb && cb();
15433
- self.mutex = false;
15629
+ self.fireReady();
15434
15630
  });
15435
15631
  };
15436
- self.mutex = true;
15437
15632
 
15438
15633
  self.meetingSearch = function(cb=null) {
15439
- var url = '/client_interface/jsonp/?switcher=GetSearchResults&get_used_formats&lang_enum=' + self.config['short_language'];
15634
+ let url = '/client_interface/jsonp/?switcher=GetSearchResults&get_used_formats&lang_enum=' + self.config['short_language'];
15440
15635
 
15441
15636
  if (self.config['formats']) {
15442
15637
  url += self.config['formats'].reduce(function(prev,id) {
@@ -15465,9 +15660,7 @@ function Crouton(config) {
15465
15660
  url += self.config['custom_query'] + '&sort_keys=' + self.config['sort_keys'];
15466
15661
  return self.getMeetings(url,cb);
15467
15662
  } else if (self.config['service_body'].length > 0) {
15468
- for (var i = 0; i < self.config['service_body'].length; i++) {
15469
- url += '&services[]=' + self.config['service_body'][i];
15470
- }
15663
+ url = self.config['service_body'].reduce((curr,item)=>curr+'&services[]='+item, url);
15471
15664
 
15472
15665
  if (self.config['recurse_service_bodies']) {
15473
15666
  url += '&recursive=1';
@@ -15480,31 +15673,47 @@ function Crouton(config) {
15480
15673
  return new Promise(function(resolve, reject) {
15481
15674
  self.meetingData = [];
15482
15675
  self.formatsData = [];
15483
- self.mutex = false;
15484
15676
  resolve([]);
15677
+ self.fireReady();
15485
15678
  });
15486
15679
  }
15680
+ }
15681
+ self.readyListener = [];
15682
+ /**
15683
+ * Add a listener for the event that the crouton instance has loaded its data and we can now go ahead and execute the shortcodes.
15684
+ * Generally, each listener corresponds to different shortcode. The main ones go over the render method, but there are also listeners
15685
+ * for [meeting_count] etc.
15686
+ * @param function callback
15687
+ */
15688
+ self.listenForReady = function(callback) {
15689
+ if (self.ready) callback();
15690
+ else self.readyListener.push(callback);
15487
15691
  };
15488
-
15489
- self.lock = function(callback) {
15490
- var self = this;
15491
- var lock_id = setInterval(function() {
15492
- if (!self.mutex) {
15493
- clearInterval(lock_id);
15494
- callback();
15495
- }
15496
- }, 100);
15692
+ /**
15693
+ * FIres the event that crouton is loaded and ready.
15694
+ */
15695
+ self.fireReady = function() {
15696
+ self.ready = true;
15697
+ self.readyListener.forEach(function(callback) {
15698
+ callback();
15699
+ });
15700
+ self.readyListener = [];
15497
15701
  };
15498
-
15499
- self.dayTab = function(day_id) {
15702
+ /**
15703
+ * Bring up the appropriate tab based on the meeting id.
15704
+ * This is only used when a meeting is selected in the msp. I consider this bloat, it is superceded by the meeting details popup available in the marker text.
15705
+ * @param string id meeting id.
15706
+ */
15707
+ self.dayTabFromId = function(id) {
15708
+ const day_id = self.meetingData.find((m)=>m.id_bigint == id).weekday_tinyint;
15500
15709
  self.hideAllPages();
15501
15710
  jQuery('.nav-tabs a[href="#tab' + day_id + '"]').tab('show');
15502
15711
  jQuery("#" + day_id).removeClass("hide").addClass("show");
15503
15712
  };
15504
- self.dayTabFromId = function(id) {
15505
- day_id = self.meetingData.find((m)=>m.id_bigint == id).weekday_tinyint;
15506
- self.dayTab(day_id);
15507
- };
15713
+ /**
15714
+ * Show a page from the table (weekday, distance, city...)
15715
+ * @param string id selector, id attribute of the HtML
15716
+ */
15508
15717
  self.showPage = function (id) {
15509
15718
  jQuery(id+" .bmlt-data-row-placeholder").each(function() {
15510
15719
  const meetingId = this.dataset.meetingid;
@@ -15517,7 +15726,11 @@ function Crouton(config) {
15517
15726
  self.addStripes();
15518
15727
  jQuery(id).removeClass("hide").addClass("show");
15519
15728
  };
15520
-
15729
+ /**
15730
+ * Bring up a view.
15731
+ * @param string viewName abstract viewname (weekday, distance, city...)
15732
+ * @param int showingNow number of items currently being displayed on the page
15733
+ */
15521
15734
  self.showView = function (viewName, showingNow=0) {
15522
15735
  if (viewName === 'distance' && !self.distanceTabAllowed) {
15523
15736
  viewName = self.config.groups ? 'city' : 'day';
@@ -15578,6 +15791,7 @@ function Crouton(config) {
15578
15791
  self.dayView();
15579
15792
  return;
15580
15793
  }
15794
+ self.currentView = field;
15581
15795
  self.lowlightButton("#day");
15582
15796
  self.lowlightButton(".groupingButton");
15583
15797
  self.highlightButton("#groupingButton_" + field);
@@ -15620,8 +15834,12 @@ function Crouton(config) {
15620
15834
  jQuery(value).addClass((index % 2) ? 'oddRow' : 'evenRow');
15621
15835
  });
15622
15836
  }
15837
+ /**
15838
+ *
15839
+ * @returns a list of the IDs of meetings matching the current filters.
15840
+ */
15623
15841
  self.calcShowingNow = function() {
15624
- var showingNow = [];
15842
+ let showingNow = [];
15625
15843
  jQuery(".bmlt-data-row:not(.hide)").each(function (index, value) {
15626
15844
  const rowId = value.id.split("-");
15627
15845
  showingNow.push(rowId[rowId.length-1]);
@@ -15644,26 +15862,13 @@ function Crouton(config) {
15644
15862
  }
15645
15863
  });
15646
15864
  this.addStripes();
15647
- var showingNow = this.calcShowingNow();
15865
+ const showingNow = this.calcShowingNow();
15648
15866
  self.updateMeetingCount(showingNow);
15649
- self.updateFilters();
15650
- if (croutonMap) croutonMap.fillMap(showingNow);
15651
- self.showView(self.currentView, showingNow.length);
15867
+ self.updateFilters(showingNow);
15868
+ if (croutonMap) croutonMap.setFilteredIds(showingNow);
15869
+ if (self.currentView !== 'map') self.showView(self.currentView, showingNow.length);
15652
15870
  };
15653
- self.resetFilter = function () {
15654
- croutonMap.filterVisible(false);
15655
- if ((self.config.map_page && self.filtering) || self.config.show_map) croutonMap.fillMap();
15656
- self.filtering = false;
15657
- self.updateFilters();
15658
- self.updateMeetingCount();
15659
- jQuery(".filter-dropdown").val(null).trigger("change");
15660
- jQuery(".group-header").removeClass("hide");
15661
- jQuery(".meeting-group").removeClass("hide");
15662
- jQuery(".bmlt-data-row").removeClass("hide");
15663
- jQuery(".evenRow").removeClass("evenRow");
15664
- jQuery(".oddRow").removeClass("oddRow");
15665
- };
15666
- self.updateFilters = function() {
15871
+ self.updateFilters = function(showingNow) {
15667
15872
  if (!self.dropdownData) return;
15668
15873
  const getId = function (row) {return row.id.replace("meeting-data-row-", "")};
15669
15874
  // The options available for this filter have to take into account all other filters, but ignore the
@@ -15686,6 +15891,12 @@ function Crouton(config) {
15686
15891
  let showing = self.meetingData.filter((m) => !(hidden.includes(m.id_bigint)));
15687
15892
  dropdown.optionsShowing = dropdown.uniqueData(showing).map((o) => dropdown.optionName(o));
15688
15893
  });
15894
+ const favoritesDropdown = self.dropdownData.find((d) => d.elementId === "filter-dropdown-favorites");
15895
+ if (!favoritesDropdown || !self.shouldOfferFavorites(showingNow)) {
15896
+ jQuery("#crouton_favorites_button").addClass("hide");
15897
+ } else {
15898
+ jQuery("#crouton_favorites_button").removeClass("hide");
15899
+ }
15689
15900
  }
15690
15901
  self.renderStandaloneMap = function (selector, context, callback=null, fitBounds=true) {
15691
15902
  hbs_Crouton['localization'] = self.localization;
@@ -15693,40 +15904,14 @@ function Crouton(config) {
15693
15904
  self.setUpPartials();
15694
15905
  croutonMap.initialize(self.createBmltMapElement(),self.meetingData,context,null,fitBounds,callback,self.config['noMap']);
15695
15906
  }
15696
- self.retrieveGeolocation = function() {
15697
- return new Promise((resolve, reject) => {
15698
- if (window.storedGeolocation) {
15699
- resolve(window.storedGeolocation);
15700
- } else if (navigator.geolocation) {
15701
- navigator.geolocation.getCurrentPosition((position) => {
15702
- window.storedGeolocation = {
15703
- latitude: position.coords.latitude,
15704
- longitude: position.coords.longitude
15705
- };
15706
- resolve(window.storedGeolocation);
15707
- }, (error) => {
15708
- reject(new Error('Error getting geolocation: ' + error.message));
15709
- });
15710
- } else {
15711
- reject(new Error('Geolocation is not supported by this browser.'));
15712
- }
15713
- });
15714
- };
15715
- self.getCurrentLocation = function(callback) {
15716
- self.gretrieveGeolocation().then(position => {
15717
- callback(position);
15718
- }).catch(error => {
15719
- jQuery('.geo').removeClass("hide").addClass("show").html(`<p>${error.message}</p>`);
15720
- });
15721
- };
15722
15907
  self.renderView = function (selector, context, callback, fitBounds) {
15723
15908
  hbs_Crouton['localization'] = self.localization;
15724
- var template = hbs_Crouton.templates['main'];
15909
+ const template = hbs_Crouton.templates['main'];
15725
15910
  jQuery(selector).html(template(context));
15726
15911
  callback();
15727
15912
  };
15728
15913
  self.updateMeetingCount = function(showingNow=null) {
15729
- var self = this;
15914
+ const self = this;
15730
15915
  let meetingCount = self.meetingData.length;
15731
15916
  if (self.meetingCountCallback) self.meetingCountCallback(meetingCount);
15732
15917
  if (self.groupCountCallback) self.groupCountCallback(
@@ -15739,8 +15924,8 @@ function Crouton(config) {
15739
15924
  }
15740
15925
  self.showingNowCount = meetingCount;
15741
15926
  jQuery(".crouton_root_service_body").each(function() {
15742
- var text = "";
15743
- var field = 'name';
15927
+ let text = "";
15928
+ let field = 'name';
15744
15929
  if (this.dataset.field) field = this.dataset.field;
15745
15930
  if (self.config['service_body'].length > 0) {
15746
15931
  const sb = self.getServiceBodyDetails(self.config['service_body'][0]);
@@ -15750,19 +15935,17 @@ function Crouton(config) {
15750
15935
  });
15751
15936
  jQuery(addLive('#bmlt_tabs_meeting_count')).text(meetingCount);
15752
15937
  jQuery(addLive('#bmlt_tabs_group_count')).each(function(){
15753
- var filteredMeetings = self.meetingData;
15754
- if (showingNow!==null) filteredMeetings = self.meetingData.filter((m) => showingNow.includes(m.id_bigint));
15938
+ const filteredMeetings = (showingNow!==null) ? self.meetingData.filter((m) => showingNow.includes(m.id_bigint)) : self.meetingData;
15755
15939
  const groups = self.config.groups ? filteredMeetings : self.convertToGroups([...filteredMeetings]);
15756
- jQuery(this).text(arrayUnique(groups).length);
15940
+ jQuery(this).text([...new Set(groups)].length);
15757
15941
  });
15758
15942
  jQuery(addLive('#bmlt_tabs_service_body_names')).each(function() {
15759
- var filteredMeetings = self.meetingData;
15760
- if (showingNow!==null) filteredMeetings = self.meetingData.filter((m) => showingNow.includes(m.id_bigint));
15761
- var ids = getUniqueValuesOfKey(filteredMeetings, 'service_body_bigint');
15762
- var me = this;
15943
+ const filteredMeetings = (showingNow!==null) ? self.meetingData.filter((m) => showingNow.includes(m.id_bigint)) : self.meetingData;
15944
+ const ids = getUniqueValuesOfKey(filteredMeetings, 'service_body_bigint');
15945
+ const me = this;
15763
15946
  self.getServiceBodies(ids, false).then(function (service_bodies) {
15764
- var n = service_bodies.length;
15765
- var names = service_bodies.map((m)=>m['name']);
15947
+ const n = service_bodies.length;
15948
+ const names = service_bodies.map((m)=>m['name']);
15766
15949
  names.sort();
15767
15950
  var ret = "";
15768
15951
  if (n===1) {
@@ -15781,16 +15964,23 @@ function Crouton(config) {
15781
15964
  });
15782
15965
  }
15783
15966
  self.getServiceBodies = function(service_bodies_id, requires_parents=true) {
15784
- var url = this.config['root_server'] + '/client_interface/jsonp/?switcher=GetServiceBodies'
15785
- + (requires_parents ? '&parents=1' : '') + getServiceBodiesQueryString(service_bodies_id);
15967
+ const url = this.config['root_server'] + '/client_interface/jsonp/?switcher=GetServiceBodies'
15968
+ + (requires_parents ? '&parents=1' : '') + self.getServiceBodiesQueryString(service_bodies_id);
15786
15969
  return fetchJsonp(url)
15787
15970
  .then(function(response) {
15788
15971
  return response.json();
15789
15972
  });
15790
15973
  };
15791
15974
 
15975
+ self.getServiceBodiesQueryString = function(service_bodies_id) {
15976
+ let service_bodies_query = "";
15977
+ for (var x = 0; x < service_bodies_id.length; x++) {
15978
+ service_bodies_query += "&services[]=" + service_bodies_id[x];
15979
+ }
15980
+ return service_bodies_query;
15981
+ }
15792
15982
  self.getMasterFormats = function() {
15793
- var url = this.config['root_server'] + '/client_interface/jsonp/?switcher=GetFormats&lang_enum=en&key_strings[]=TC&key_strings[]=VM&key_strings[]=HY';
15983
+ const url = this.config['root_server'] + '/client_interface/jsonp/?switcher=GetFormats&lang_enum=en&key_strings[]=TC&key_strings[]=VM&key_strings[]=HY';
15794
15984
  return fetchJsonp(url)
15795
15985
  .then(function(response) {
15796
15986
  return response.json();
@@ -15812,16 +16002,16 @@ function Crouton(config) {
15812
16002
  self.handlebarMapOptions.lng = parseFloat(meetingDetailsData.longitude);
15813
16003
  return "<div id='bmlt-handlebars-map' class='bmlt-map'></div>"
15814
16004
  });
15815
- var parser = new DOMParser();
16005
+ const parser = new DOMParser();
15816
16006
 
15817
16007
  while (elements.length > 0) {
15818
- var element = elements.item(0);
16008
+ const element = elements.item(0);
15819
16009
  if (!element.firstChild) {
15820
16010
  console.log('<bmlt-handlebar> tag must have at least one child');
15821
16011
  element.remove();
15822
16012
  continue;
15823
16013
  }
15824
- var templateString = '';
16014
+ let templateString = '';
15825
16015
  if (element.firstChild.nodeType === 1) {
15826
16016
  if (!element.firstChild.firstChild || element.firstChild.firstChild.nodeType !== 3) {
15827
16017
  console.log('<bmlt-handlebar> tag: cannot find textnode');
@@ -15834,13 +16024,13 @@ function Crouton(config) {
15834
16024
  }
15835
16025
  var handlebarResult;
15836
16026
  try {
15837
- var template = crouton_Handlebars.compile(templateString);
16027
+ const template = crouton_Handlebars.compile(templateString);
15838
16028
  handlebarResult = template(meetingDetailsData);
15839
16029
  } catch (e) {
15840
16030
  console.log(e);
15841
16031
  handlebarResult = e.message;
15842
16032
  }
15843
- var htmlDecode = parser.parseFromString('<body>'+handlebarResult+'</body>', "text/html");
16033
+ const htmlDecode = parser.parseFromString('<body>'+handlebarResult+'</body>', "text/html");
15844
16034
  if (!htmlDecode.body || !htmlDecode.body.firstChild) {
15845
16035
  console.log('<bmlt-handlebar> tag: could not parse the Handlebars result');
15846
16036
  element.replaceWith('<bmlt-handlebar> tag: could not parse the Handlebars result');
@@ -15912,7 +16102,12 @@ function Crouton(config) {
15912
16102
  n = n.replace(/PM|pm/g, x => ampm['PM']);
15913
16103
  return n;
15914
16104
  }
15915
- self.enrichMeetings = function (meetingData) {
16105
+ /**
16106
+ * Take raw meeting data as returned from server adding values that should be conveniently displayed.
16107
+ * @param array meetingData
16108
+ * @returns the array with enriched data
16109
+ */
16110
+ self.enrichMeetings = function(meetingData) {
15916
16111
  var meetings = [];
15917
16112
 
15918
16113
  let queryStringChar = '?';
@@ -15943,8 +16138,8 @@ function Crouton(config) {
15943
16138
  meetingData[m]['day_of_the_week'] = meetingData[m]['start_time_raw'].isoWeekday() === 7 ? 1 : meetingData[m]['start_time_raw'].isoWeekday() + 1;
15944
16139
  meetingData[m]['formatted_day'] = self.localization.getDayOfTheWeekWord(meetingData[m]['day_of_the_week']);
15945
16140
 
15946
- var formats = meetingData[m]['formats'].split(",");
15947
- var formats_expanded = [];
16141
+ const formats = meetingData[m]['formats'].split(",");
16142
+ const formats_expanded = [];
15948
16143
  let formatRootServer = self.formatsData.filter((f)=>f['root_server_uri'] == meetingData[m]['root_server_uri']);
15949
16144
  meetingData[m]['wheelchair'] = false;
15950
16145
  for (var f = 0; f < formats.length; f++) {
@@ -15966,14 +16161,13 @@ function Crouton(config) {
15966
16161
 
15967
16162
  meetingData[m]['venue_type'] = parseInt(meetingData[m]['venue_type']);
15968
16163
  meetingData[m]['venue_type_name'] = getVenueTypeName(meetingData[m]);
15969
- meetingData[m]['formats_expanded'] = formats_expanded;
15970
- var addressParts = [
16164
+ meetingData[m]['formats_expanded'] = formats_expanded.sortByKey('name');
16165
+ const addressParts = [
15971
16166
  meetingData[m]['location_street'],
15972
16167
  meetingData[m]['location_municipality'].trim(),
15973
16168
  meetingData[m]['location_province'].trim(),
15974
16169
  meetingData[m]['location_postal_code_1'].trim()
15975
- ];
15976
- addressParts.clean();
16170
+ ].filter((value)=>value!=="");
15977
16171
  meetingData[m]['formatted_address'] = addressParts.join(", ");
15978
16172
  meetingData[m]['formatted_location_info'] =
15979
16173
  meetingData[m]['location_info'] != null
@@ -15992,7 +16186,7 @@ function Crouton(config) {
15992
16186
  }
15993
16187
  }
15994
16188
 
15995
- var serviceBodyInfo = self.getServiceBodyDetails(meetingData[m]['service_body_bigint'])
16189
+ const serviceBodyInfo = self.getServiceBodyDetails(meetingData[m]['service_body_bigint'])
15996
16190
  meetingData[m]['serviceBodyUrl'] = serviceBodyInfo["url"];
15997
16191
  meetingData[m]['serviceBodyPhone'] = serviceBodyInfo["helpline"];
15998
16192
  meetingData[m]['serviceBodyName'] = serviceBodyInfo["name"];
@@ -16000,7 +16194,7 @@ function Crouton(config) {
16000
16194
  meetingData[m]['serviceBodyContactEmail'] = serviceBodyInfo["contact_email"];
16001
16195
  meetingData[m]['serviceBodyType'] = self.localization.getServiceBodyType(serviceBodyInfo["type"]);
16002
16196
 
16003
- var parentBodyInfo = self.getServiceBodyDetails(serviceBodyInfo["parent_id"]);
16197
+ const parentBodyInfo = self.getServiceBodyDetails(serviceBodyInfo["parent_id"]);
16004
16198
  if (parentBodyInfo !== undefined) {
16005
16199
  meetingData[m]['parentServiceBodyId'] = serviceBodyInfo["parent_id"];
16006
16200
  meetingData[m]['parentServiceBodyUrl'] = parentBodyInfo["url"];
@@ -16029,7 +16223,27 @@ function Crouton(config) {
16029
16223
  return self.convertToGroups(meetings);
16030
16224
  }
16031
16225
  return meetings;
16032
- };
16226
+ }
16227
+ // [deprecated] Retire after root server 2.16.4 is rolled out everywhere.
16228
+ const masterFormatVenueType = {
16229
+ IN_PERSON: "IN_PERSON",
16230
+ VIRTUAL: "VIRTUAL",
16231
+ }
16232
+
16233
+ function getVenueTypeName(data) {
16234
+ if (data['venue_type'] === venueType.HYBRID || getFormats(data).includes(getMasterFormatId('HY', data))) {
16235
+ return [crouton.localization.getVenueType(masterFormatVenueType.VIRTUAL), crouton.localization.getVenueType(masterFormatVenueType.IN_PERSON)];
16236
+ } else if (data['venue_type'] === venueType.VIRTUAL || getFormats(data).includes(getMasterFormatId('VM', data))) {
16237
+ return [crouton.localization.getVenueType(masterFormatVenueType.VIRTUAL)];
16238
+ } else {
16239
+ return [crouton.localization.getVenueType(masterFormatVenueType.IN_PERSON)];
16240
+ }
16241
+ }
16242
+ /**
16243
+ * Convert from individual meetings to groups.
16244
+ * @param array meetings
16245
+ * @returns
16246
+ */
16033
16247
  self.convertToGroups = function(meetings) {
16034
16248
  if (!meetings || !meetings.length) return [];
16035
16249
  if (meetings[0].hasOwnProperty('membersOfGroup')) return meetings;
@@ -16076,6 +16290,11 @@ function Crouton(config) {
16076
16290
  });
16077
16291
  return groups;
16078
16292
  }
16293
+ /**
16294
+ * Update the distances displyed after geocoding or geolocation.
16295
+ * @param boolean initial
16296
+ * @returns
16297
+ */
16079
16298
  Crouton.prototype.updateDistances = function(initial=false) {
16080
16299
  const self = this;
16081
16300
  var knt = 0;
@@ -16110,8 +16329,8 @@ function Crouton(config) {
16110
16329
  });
16111
16330
  }
16112
16331
  const sorted = parent.children().sort(function (a, b) {
16113
- const idA =parseFloat( jQuery(a).data('meetingid').replace("meeting-data-row-", ""));
16114
- const idB =parseFloat( jQuery(b).data('meetingid').replace("meeting-data-row-", ""));
16332
+ const idA =parseFloat( (jQuery(a).data('meetingid') ?? jQuery(a).attr('id')).replace("meeting-data-row-", ""));
16333
+ const idB =parseFloat( (jQuery(b).data('meetingid') ?? jQuery(b).attr('id')).replace("meeting-data-row-", ""));
16115
16334
  const dataA = self.meetingData.find((m) => m.id_bigint==idA);
16116
16335
  const dataB = self.meetingData.find((m) => m.id_bigint==idB);
16117
16336
  const distanceA = dataA ? parseFloat(dataA['distance_in_km']) : Number.POSITIVE_INFINITY;
@@ -16143,8 +16362,6 @@ function Crouton(config) {
16143
16362
  ? "<td>{{> meetingStackedRow}}</td>"
16144
16363
  : hbs_Crouton.templates['meeting3ColumnRow'])
16145
16364
  );
16146
-
16147
-
16148
16365
  self.registerPartial("meetingDataTemplate", self.config['meeting_data_template']);
16149
16366
  self.registerPartial("meetingDataTemplate", self.config['meeting_data_template']);
16150
16367
  self.registerPartial("metaDataTemplate", self.config['metadata_template']);
@@ -16162,6 +16379,14 @@ function Crouton(config) {
16162
16379
  handlebarsExtensions.registerHelpers();
16163
16380
  handlebarsExtensions.registerPartials(self.config.groups);
16164
16381
  }
16382
+ self.getServiceBodyDetails = function(serviceBodyId) {
16383
+ return this.all_service_bodies.find((s)=>s['id'] === serviceBodyId)
16384
+ }
16385
+ /**
16386
+ * Calculate the distances sfter geocoding or geolocation, adding them to the meeting data.
16387
+ * @param boolean initial
16388
+ * @returns
16389
+ */
16165
16390
  self.calculateDistance = function(meetingData) {
16166
16391
  meetingData['distance'] = '';
16167
16392
  if (meetingData['venue_type'] != 2) {
@@ -16205,19 +16430,21 @@ function Crouton(config) {
16205
16430
  self.getUsedNext24 = function(meetings) {
16206
16431
  return [{name: 'Next24', value: 1}];
16207
16432
  }
16208
- self.isEmpty = function(obj) {
16209
- for (var key in obj) {
16210
- if(obj.hasOwnProperty(key))
16211
- return false;
16212
- }
16213
- return true;
16214
- };
16433
+ self.getUsedFavorites = function(meetings) {
16434
+ return [{name: 'Favorite', value: 1}]
16435
+ }
16215
16436
  self.createBmltMapElement = function() {
16216
16437
  if (!document.getElementById('bmlt-map')) {
16217
16438
  jQuery("#bmlt-tabs").before("<div id='bmlt-map' class='bootstrap-bmlt bmlt-map "+self.localization.getWord('css-direction')+" bmlt_map_container_div'></div>");
16218
16439
  }
16219
16440
  return 'bmlt-map';
16220
16441
  }
16442
+ self.createLocationSearchElement = function() {
16443
+ if (!document.getElementById('bmlt-location-search')) {
16444
+ jQuery("#bmlt-header").append("<div id='bmlt-location-search' class='bootstrap-bmlt bmlt-location-search "+self.localization.getWord('css-direction')+" bmlt_location_search_container_div'></div>");
16445
+ }
16446
+ return 'bmlt-location-search';
16447
+ }
16221
16448
  if (typeof window.croutonMap === 'undefined') {
16222
16449
  window.croutonMap = new MeetingMap(self.config);
16223
16450
  if (self.config['map_search']) self.searchMap();
@@ -16227,7 +16454,7 @@ function Crouton(config) {
16227
16454
  }
16228
16455
 
16229
16456
  Crouton.prototype.setConfig = function(config) {
16230
- var self = this;
16457
+ const self = this;
16231
16458
  const deprecatedNames = {
16232
16459
  button_filters: 'grouping_buttons',
16233
16460
  button_format_filters: 'formattype_grouping_buttons',
@@ -16288,43 +16515,27 @@ Crouton.prototype.setConfig = function(config) {
16288
16515
  console.log("Error parsing custom translations: " + e.message);
16289
16516
  }
16290
16517
  }
16291
- };
16292
-
16293
- Crouton.prototype.reset = function() {
16294
- var self = this;
16295
- jQuery("#custom-css").remove();
16296
- jQuery("#" + self.config["placeholder_id"]).html("");
16297
- };
16298
-
16299
- Crouton.prototype.doFilters = function() {
16300
- return this.filterMeetingsFromView();
16301
- }
16302
- Crouton.prototype.getServiceBodyDetails = function(serviceBodyId) {
16303
- var self = this;
16304
- for (var s = 0; s < self.all_service_bodies.length; s++) {
16305
- var service_body = self.all_service_bodies[s];
16306
- if (service_body['id'] === serviceBodyId) {
16307
- return service_body;
16308
- }
16309
- }
16518
+ if (self.config.format_list_style !== 'formatNames') self.config.format_list_style = 'formatKeys';
16310
16519
  }
16311
-
16520
+ /**
16521
+ * This supports the [bmlt_handlebars] shortcode, which allows a meeting's details to be inserted into a page.
16522
+ */
16312
16523
  Crouton.prototype.doHandlebars = function() {
16313
16524
  var elements = document.getElementsByTagName('bmlt-handlebar');
16314
16525
  if (elements.length === 0) {
16315
16526
  console.log('No <bmlt-handlebar> tags found');
16316
16527
  return;
16317
16528
  };
16318
- var self = this;
16319
- self.lock(function() {
16320
- if (self.isEmpty(self.meetingData)) {
16529
+ const self = this;
16530
+ self.listenForReady(function() {
16531
+ if (!self.meetingData || self.meetingData.length === 0) {
16321
16532
  for (let i = 0; i < elements.length; i++) {
16322
16533
  var element = elements.item(i);
16323
16534
  element.innerHTML = "Meeting not found!";
16324
16535
  }
16325
16536
  return;
16326
16537
  }
16327
- var promises = [self.getServiceBodies([self.meetingData[0]['service_body_bigint']])];
16538
+ const promises = [self.getServiceBodies([self.meetingData[0]['service_body_bigint']])];
16328
16539
  Promise.all(promises)
16329
16540
  .then(function(data) {
16330
16541
  hbs_Crouton['localization'] = self.localization;
@@ -16345,10 +16556,21 @@ Crouton.prototype.doHandlebars = function() {
16345
16556
  });
16346
16557
  });
16347
16558
  };
16348
-
16559
+ /**
16560
+ * Sometimes the logic in the map has to decide whether to let the map implementation (google or leaflet) do something, or just do the calculation
16561
+ * itself. So we have to ask crouton if the map is showing or not.
16562
+ * @returns boolean
16563
+ */
16564
+ Crouton.prototype.isEmbeddedMapShowing = function() {
16565
+ if (this.config['show_map']) return true;
16566
+ const embeddedMap = document.getElementById("byfield_embeddedMapPage");
16567
+ if (embeddedMap) {
16568
+ return !embeddedMap.classList.contains('hide');
16569
+ }
16570
+ return true;
16571
+ }
16349
16572
  Crouton.prototype.meetingModal = function(meetingId) {
16350
- let self = this;
16351
- this.openMeetingModal(self.meetingData.find((m) => m.id_bigint == meetingId));
16573
+ this.openMeetingModal(this.meetingData.find((m) => m.id_bigint == meetingId));
16352
16574
  return;
16353
16575
  }
16354
16576
  Crouton.prototype.openMeetingModal = function(meeting) {
@@ -16369,7 +16591,7 @@ Crouton.prototype.openMeetingModal = function(meeting) {
16369
16591
  croutonMap.loadPopupMap("bmlt-handlebars-map", meeting, {
16370
16592
  lat: parseFloat(meeting.latitude),
16371
16593
  lng: parseFloat(meeting.longitude),
16372
- zoom: 14
16594
+ zoom: self.config.focusedMeetingPopupZoomLevel ?? 14
16373
16595
  });
16374
16596
  let visibleMeetings = jQuery('.bmlt-data-row:visible');
16375
16597
  let index = -1;
@@ -16410,8 +16632,11 @@ Crouton.prototype.openMeetingModal = function(meeting) {
16410
16632
  mm.getElementsByClassName('modal-right').item(0).addEventListener("click", ev=>doSwipe("left"));
16411
16633
  }
16412
16634
  }
16635
+ /**
16636
+ * Execute the [crouton_map] shortcode.
16637
+ */
16413
16638
  Crouton.prototype.searchMap = function() {
16414
- var self = this;
16639
+ const self = this;
16415
16640
  self.distanceTabAllowed = true;
16416
16641
  if (!self.config.map_search || typeof self.config.map_search !== 'object') {
16417
16642
  self.config.map_search = {
@@ -16429,12 +16654,6 @@ Crouton.prototype.searchMap = function() {
16429
16654
  }
16430
16655
  self.config['map_page'] = false;
16431
16656
  self.config['show_map'] = false;
16432
- var body = jQuery("body");
16433
- if (self.config['theme'] !== '') {
16434
- body.append("<div id='custom-css'><link rel='stylesheet' type='text/css' href='" + self.config['template_path'] + '/themes/' + self.config['theme'] + ".css'>");
16435
- }
16436
-
16437
- body.append("<div id='custom-css'><style type='text/css'>" + self.config['custom_css'] + "</style></div>");
16438
16657
 
16439
16658
  self.meetingData = null;
16440
16659
  self.renderStandaloneMap("#" + self.config['placeholder_id'], {
@@ -16451,29 +16670,26 @@ Crouton.prototype.searchMap = function() {
16451
16670
  "location": {'latitude':0,'longitude':0,'zoom':10} // TODO: Where is this used?
16452
16671
  });
16453
16672
  }
16673
+ /**
16674
+ * This methods does the main work of creating the crouton table.
16675
+ * @param boolean doMeetingMap MeetingMap is the old name for the [bmlt_map] shortcode.
16676
+ * @param boolean fitBounds Expand the scaale and center of the map to contain all meetings.
16677
+ */
16454
16678
  Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16455
- var self = this;
16456
-
16457
- self.lock(function() {
16458
- var body = jQuery("body");
16459
- if (self.config['theme'] !== '') {
16460
- body.append("<div id='custom-css'><link rel='stylesheet' type='text/css' href='" + self.config['template_path'] + '/themes/' + self.config['theme'] + ".css'>");
16461
- }
16462
-
16463
- body.append("<div id='custom-css'><style type='text/css'>" + self.config['custom_css'] + "</style></div>");
16679
+ const self = this;
16464
16680
 
16465
- if (self.isEmpty(self.meetingData)) {
16681
+ self.listenForReady(function() {
16682
+ if (!self.meetingData || self.meetingData.length === 0) {
16466
16683
  jQuery('#please-wait').remove();
16467
16684
  self.showMessage("No meetings found for parameters specified.");
16468
- alert("No meetings found for parameters specified.");
16469
16685
  if (self.config['refresh_map']) {
16470
- croutonMap.refreshMeetings(self.meetingData, fitBounds, true);
16686
+ croutonMap.refreshMeetings(self.meetingData, fitBounds);
16471
16687
  }
16472
16688
  return;
16473
16689
  }
16474
16690
 
16475
16691
  self.unique_service_bodies_ids = getUniqueValuesOfKey(self.meetingData, 'service_body_bigint').sort();
16476
- var promises = [self.getMasterFormats(), self.getServiceBodies(self.unique_service_bodies_ids)];
16692
+ const promises = [self.getMasterFormats(), self.getServiceBodies(self.unique_service_bodies_ids)];
16477
16693
  Promise.all(promises)
16478
16694
  .then(function(data) {
16479
16695
  self.all_service_bodies = [];
@@ -16510,7 +16726,7 @@ Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16510
16726
  var weekdaysData = [];
16511
16727
  while (day_counter < 7) {
16512
16728
  var day = self.config.day_sequence[day_counter];
16513
- var daysOfTheWeekMeetings = enrichedMeetingData.filterByObjectKeyValue('day_of_the_week', day);
16729
+ var daysOfTheWeekMeetings = enrichedMeetingData.filter((meeting)=>meeting['day_of_the_week'] == day);
16514
16730
  weekdaysData.push({
16515
16731
  "day": day,
16516
16732
  "meetings": daysOfTheWeekMeetings
@@ -16526,7 +16742,7 @@ Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16526
16742
  if (groupByName.startsWith('distance')) continue;
16527
16743
  var groupByData = getUniqueValuesOfKey(daysOfTheWeekMeetings, groupByName).sort();
16528
16744
  for (var i = 0; i < groupByData.length; i++) {
16529
- var groupByMeetings = daysOfTheWeekMeetings.filterByObjectKeyValue(groupByName, groupByData[i]);
16745
+ var groupByMeetings = daysOfTheWeekMeetings.filter((meeting)=>meeting[groupByName] == groupByData[i]);
16530
16746
  if (groupingButtonsData.hasOwnProperty(groupByName) && groupingButtonsData[groupByName].hasOwnProperty(groupByData[i])) {
16531
16747
  groupingButtonsData[groupByName][groupByData[i]] = groupingButtonsData[groupByName][groupByData[i]].concat(groupByMeetings);
16532
16748
  } else if (groupingButtonsData.hasOwnProperty(groupByName)) {
@@ -16601,7 +16817,7 @@ Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16601
16817
  self.dropdownData = [];
16602
16818
  if (self.config.has_days) self.dropdownData.push(
16603
16819
  {placeholder: self.localization.getWord('weekday'), pointer: 'weekdays', elementId: "filter-dropdown-weekdays",
16604
- uniqueData: (meetings) => sortListByList(getUniqueValuesOfKey(meetings, "formatted_day"), self.dayNamesSequenced),
16820
+ uniqueData: (meetings) => self.sortListByList(getUniqueValuesOfKey(meetings, "formatted_day"), self.dayNamesSequenced),
16605
16821
  objectPointer: convertToPunyCode, optionName: (s)=>s});
16606
16822
  if (self.config.has_states) self.dropdownData.push(
16607
16823
  {placeholder: self.localization.getWord('states'), pointer: 'States', elementId: "filter-dropdown-states",
@@ -16663,6 +16879,10 @@ Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16663
16879
  {placeholder: '', pointer: 'next24', elementId: "filter-dropdown-next24",
16664
16880
  uniqueData: (meetings) => self.getUsedNext24(meetings),
16665
16881
  objectPointer: (s)=>s.value, optionName: (s)=>s.name});
16882
+ if (self.config.has_favorites) self.dropdownData.push(
16883
+ {placeholder: '', pointer: 'favorite', elementId: "filter-dropdown-favorites",
16884
+ uniqueData: (meetings) => self.getUsedFavorites(meetings),
16885
+ objectPointer: (s)=>s.value, optionName: (s)=>s.name});
16666
16886
  let renderer = doMeetingMap ? self.renderStandaloneMap : self.renderView;
16667
16887
  renderer("#" + self.config['placeholder_id'], {
16668
16888
  "config": self.config,
@@ -16681,20 +16901,30 @@ Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16681
16901
  jQuery('#groupingButton_distance_in_km').addClass('hide');
16682
16902
  }
16683
16903
  self.addStripes();
16684
- self.calcShowingNow()
16904
+ const showingNow = self.calcShowingNow();
16685
16905
  self.updateMeetingCount();
16686
16906
  jQuery('#please-wait').remove();
16687
16907
  if (self.config['map_search'] != null || self.config['show_map']) {
16688
16908
  jQuery(".bmlt-data-row").css({cursor: "pointer"});
16689
16909
  jQuery(".bmlt-data-row").click(function (e) {
16690
- if (e.target.tagName !== 'A')
16910
+ if (e.target.tagName !== 'A' && !e.target.id.startsWith('crouton-favorite-')) {
16691
16911
  croutonMap.rowClick(parseInt(this.id.replace("meeting-data-row-", "")));
16912
+ }
16692
16913
  });
16693
16914
  }
16694
16915
 
16695
16916
  jQuery("#" + self.config['placeholder_id']).addClass("bootstrap-bmlt");
16696
16917
  jQuery("#filter-dropdown-visibile").removeClass("crouton-select").addClass("hide");
16918
+ jQuery("#filter-dropdown-visibile").parent().addClass("hide");
16697
16919
  jQuery("#filter-dropdown-next24").removeClass("crouton-select").addClass("hide");
16920
+ jQuery("#filter-dropdown-next24").parent().addClass("hide");
16921
+ jQuery("#filter-dropdown-favorites").removeClass("crouton-select").addClass("hide");
16922
+ jQuery("#filter-dropdown-favorites").parent().addClass("hide");
16923
+ if (self.shouldOfferFavorites(showingNow)) {
16924
+ jQuery("#crouton_favorites_button").removeClass("hide");
16925
+ } else {
16926
+ jQuery("#crouton_favorites_button").addClass("hide");
16927
+ }
16698
16928
  jQuery(".crouton-select").select2({
16699
16929
  dropdownAutoWidth: true,
16700
16930
  allowClear: false,
@@ -16731,6 +16961,57 @@ Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16731
16961
  jQuery('.filter-dropdown').on('select2:select', function (e) {
16732
16962
  self.filterMeetingsFromView();
16733
16963
  });
16964
+ jQuery('#crouton_favorites_button').on('click', function (e) {
16965
+ if (self.favoritesOn) {
16966
+ self.favoritesOn = false;
16967
+ jQuery("#filter-dropdown-favorites").val("a-");
16968
+ self.lowlightButton("#crouton_favorites_button");
16969
+ } else {
16970
+ self.favoritesOn = true;
16971
+ jQuery("#filter-dropdown-favorites").val("a-1");
16972
+ self.highlightButton("#crouton_favorites_button");
16973
+ }
16974
+ self.filterMeetingsFromView();
16975
+ return;
16976
+ });
16977
+ if (!self.config['has_favorites'] || !self.config['header']) {
16978
+ jQuery(".favorite-icon").addClass("hide");
16979
+ }
16980
+ jQuery(document).on('click', '.crouton-favorite', function(e) {
16981
+ e.preventDefault();
16982
+ e.stopPropagation();
16983
+ const meetingId = parseInt(this.id.replace("crouton-favorite-", ""));
16984
+ const localStorageKey = "crouton-favorites";
16985
+ const favorites = JSON.parse(localStorage.getItem(localStorageKey) || "[]");
16986
+ const index = favorites.indexOf(self.config.root_server + "_" + meetingId);
16987
+ const row = e.target.closest(".bmlt-data-row");
16988
+ let shouldFilterMeetings = self.favoritesOn;
16989
+ const showingNow = self.calcShowingNow();
16990
+ const favoritesButtonHidden = jQuery("#crouton_favorites_button").hasClass("hide");
16991
+ if (index !== -1) {
16992
+ favorites.splice(index, 1);
16993
+ e.target.classList.remove("glyphicon-heart");
16994
+ e.target.classList.add("glyphicon-heart-empty");
16995
+ row.setAttribute("data-favorite", 0);
16996
+ } else {
16997
+ shouldFilterMeetings = favoritesButtonHidden;
16998
+ favorites.push(self.config.root_server + "_" + meetingId);
16999
+ e.target.classList.remove("glyphicon-heart-empty");
17000
+ e.target.classList.add("glyphicon-heart");
17001
+ row.setAttribute("data-favorite", 1);
17002
+ }
17003
+ localStorage.setItem(localStorageKey, JSON.stringify(favorites));
17004
+ if (!self.shouldOfferFavorites(showingNow)) {
17005
+ shouldFilterMeetings = true;
17006
+ self.favoritesOn = false;
17007
+ jQuery("#filter-dropdown-favorites").val("a-");
17008
+ self.lowlightButton("#crouton_favorites_button");
17009
+ jQuery("#crouton_favorites_button").addClass("hide");
17010
+ }
17011
+ if (shouldFilterMeetings) {
17012
+ self.filterMeetingsFromView();
17013
+ }
17014
+ });
16734
17015
 
16735
17016
  jQuery("#day").on('click', function () {
16736
17017
  self.showView('day');
@@ -16756,8 +17037,8 @@ Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16756
17037
  jQuery(this).tab('show');
16757
17038
  });
16758
17039
 
16759
- var d = new Date();
16760
- var n = d.getDay();
17040
+ const d = new Date();
17041
+ let n = d.getDay();
16761
17042
  n++;
16762
17043
  jQuery('.nav-tabs a[href="#tab' + n + '"]').tab('show');
16763
17044
  jQuery('#tab' + n).show();
@@ -16779,27 +17060,46 @@ Crouton.prototype.render = function(doMeetingMap = false, fitBounds=true) {
16779
17060
  if (self.meetingData.filter(m => m.venue_type != 2).length==0) {
16780
17061
  jQuery('#groupingButton_embeddedMapPage').addClass('hide');
16781
17062
  }
16782
- else croutonMap.initialize('byfield_embeddedMapPage', self.meetingData, null, null, fitBoundsInitial);
17063
+ else {
17064
+ croutonMap.initialize('byfield_embeddedMapPage', self.meetingData, null, null, fitBoundsInitial);
17065
+ if (self.config['has_geolocation'] && self.config['header']) jQuery('#'+self.createLocationSearchElement()).append(croutonMap.createLocationSearchButton());
17066
+ }
16783
17067
  }
16784
17068
  if (self.config['refresh_map']) {
16785
- croutonMap.refreshMeetings(self.meetingData, fitBounds, true);
17069
+ croutonMap.refreshMeetings(self.meetingData, fitBounds);
16786
17070
  }
16787
17071
  if (self.config['view_by'] == 'map' && !self.config['map_page'])
16788
17072
  self.config['view_by'] = 'day';
16789
17073
  self.showView(self.config['view_by'], self.meetingData.length);
16790
- if (self.config['on_complete'] != null && isFunction(self.config['on_complete'])) {
17074
+ if (self.config['on_complete'] != null && {}.toString.call(self.config['on_complete']) === '[object Function]') {
16791
17075
  self.config['on_complete']();
16792
17076
  }
16793
- }, !doMeetingMap);
17077
+ }, !doMeetingMap || (!self.config['lat'] && !self.config['lng']));
16794
17078
  });
16795
17079
  });
16796
- Crouton.prototype.forceShowMap = function() {
16797
- if (this.config.map_page && jQuery('#byfield_embeddedMapPage').hasClass('hide')) {
16798
- this.mapView();
17080
+ self.shouldOfferFavorites = function(showingNow) {
17081
+ if (!self.config['has_favorites']) return false;
17082
+ const localStorageKey = "crouton-favorites";
17083
+ const favorites = JSON.parse(localStorage.getItem(localStorageKey) || "[]");
17084
+ for (let i = 0; i < favorites.length; i++) {
17085
+ const split = favorites[i].split("_");
17086
+ const meetingId = split[split.length-1];
17087
+ if (showingNow.includes(meetingId)) return true;
17088
+ }
17089
+ return false;
17090
+ }
17091
+ self.sortListByList = function(source, truth) {
17092
+ var goal = [];
17093
+ for (var x = 0; x < truth.length; x++) {
17094
+ for (var y = 0; y < source.length; y++) {
17095
+ if (truth[x] === source[y]) {
17096
+ goal.push(source[y])
17097
+ }
17098
+ }
16799
17099
  }
17100
+ return goal;
16800
17101
  }
16801
17102
  };
16802
-
16803
17103
  // [deprecated] Retire after root server 2.16.4 is rolled out everywhere.
16804
17104
  function getMasterFormatId(code, data) {
16805
17105
  for (var f = 0; f < crouton.masterFormatCodes.length; f++) {
@@ -16810,28 +17110,6 @@ function getMasterFormatId(code, data) {
16810
17110
  }
16811
17111
  }
16812
17112
 
16813
- // [deprecated] Retire after root server 2.16.4 is rolled out everywhere.
16814
- var masterFormatVenueType = {
16815
- IN_PERSON: "IN_PERSON",
16816
- VIRTUAL: "VIRTUAL",
16817
- }
16818
-
16819
- var venueType = {
16820
- IN_PERSON: 1,
16821
- VIRTUAL: 2,
16822
- HYBRID: 3,
16823
- }
16824
-
16825
- function getVenueTypeName(data) {
16826
- if (data['venue_type'] === venueType.HYBRID || inArray(getMasterFormatId('HY', data), getFormats(data))) {
16827
- return [crouton.localization.getVenueType(masterFormatVenueType.VIRTUAL), crouton.localization.getVenueType(masterFormatVenueType.IN_PERSON)];
16828
- } else if (data['venue_type'] === venueType.VIRTUAL || inArray(getMasterFormatId('VM', data), getFormats(data))) {
16829
- return [crouton.localization.getVenueType(masterFormatVenueType.VIRTUAL)];
16830
- } else {
16831
- return [crouton.localization.getVenueType(masterFormatVenueType.IN_PERSON)];
16832
- }
16833
- }
16834
-
16835
17113
  // TODO: Change this logic when https://github.com/bmlt-enabled/bmlt-root-server/issues/353 is released and rolled out everywhere.
16836
17114
  function getFormats(data) {
16837
17115
  return data['formats'] !== "" ? data['format_shared_id_list'].split(",") : [];
@@ -16847,17 +17125,6 @@ function getUniqueValuesOfKey(array, key){
16847
17125
  return carry;
16848
17126
  }, []);
16849
17127
  }
16850
-
16851
- function getValuesFromObject(o) {
16852
- var arr = [];
16853
- for (key in o) {
16854
- if (o.hasOwnProperty(key)) {
16855
- arr.push(o[key]);
16856
- }
16857
- }
16858
-
16859
- return arr;
16860
- }
16861
17128
  function getUniqueFormats(array){
16862
17129
  return array.reduce(function(carry, val){
16863
17130
  if (!(val.formats_expanded)) return carry;
@@ -16875,13 +17142,13 @@ function getUniqueFormatsOfType(array, type){
16875
17142
  },[]).sortByKey('name');
16876
17143
  }
16877
17144
  Crouton.prototype.renderMeetingCount = function() {
16878
- var self = this;
16879
- self.lock(function() {
17145
+ const self = this;
17146
+ self.listenForReady(function() {
16880
17147
  self.updateMeetingCount()
16881
17148
  });
16882
17149
  }
16883
17150
  Crouton.prototype.simulateFilterDropdown = function() {
16884
- self = this;
17151
+ const self = this;
16885
17152
  jQuery('.bmlt-page:not(#byfield_embeddedMapPage)').each(function () {
16886
17153
  self.hidePage(this);
16887
17154
  });
@@ -16920,76 +17187,12 @@ Crouton.prototype.getAdjustedDateTime = function(meeting_day, meeting_time, meet
16920
17187
 
16921
17188
  return meeting_date_time_obj;
16922
17189
  };
16923
-
16924
- function arrayUnique(a, b, c) {
16925
- b = a.length;
16926
- while (c = --b)
16927
- while (c--) a[b] !== a[c] || a.splice(c, 1);
16928
- return a
16929
- }
16930
-
16931
- function sortListByList(source, truth) {
16932
- var goal = [];
16933
- for (var x = 0; x < truth.length; x++) {
16934
- for (var y = 0; y < source.length; y++) {
16935
- if (truth[x] === source[y]) {
16936
- goal.push(source[y])
16937
- }
16938
- }
16939
- }
16940
-
16941
- return goal;
16942
- }
16943
-
16944
- function inArray(needle, haystack) {
16945
- return haystack.indexOf(needle) !== -1;
16946
- }
16947
-
16948
- function isFunction(functionToCheck) {
16949
- return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
16950
- }
16951
-
16952
- function getServiceBodiesQueryString(service_bodies_id) {
16953
- var service_bodies_query = "";
16954
- for (var x = 0; x < service_bodies_id.length; x++) {
16955
- service_bodies_query += "&services[]=" + service_bodies_id[x];
16956
- }
16957
- return service_bodies_query;
16958
- }
16959
-
16960
- Array.prototype.clone = function() {
16961
- return this.slice();
17190
+ // TODO: why can't this be a const? If I set it to const, then I get an error from bootstrap???!!!!
17191
+ var venueType = {
17192
+ IN_PERSON: 1,
17193
+ VIRTUAL: 2,
17194
+ HYBRID: 3,
16962
17195
  }
16963
-
16964
- Array.prototype.filterByObjectKeyValue = function(key, value) {
16965
- var ret = [];
16966
- for (var i = 0; i < this.length; i++) {
16967
- if (this[i][key] === value) {
16968
- ret.push(this[i])
16969
- }
16970
- }
16971
-
16972
- return ret;
16973
- };
16974
-
16975
- Array.prototype.getArrayItemByObjectKeyValue = function(key, value) {
16976
- for (var i = 0; i < this.length; i++) {
16977
- if (this[i][key] === value) {
16978
- return this[i];
16979
- }
16980
- }
16981
- };
16982
-
16983
- Array.prototype.clean = function() {
16984
- for (var i = 0; i < this.length; i++) {
16985
- if (this[i] === "") {
16986
- this.splice(i, 1);
16987
- i--;
16988
- }
16989
- }
16990
- return this;
16991
- };
16992
-
16993
17196
  Array.prototype.sortByKey = function (key) {
16994
17197
  this.sort(function (a, b) {
16995
17198
  if (a[key] < b[key])
@@ -17033,21 +17236,14 @@ function swipedetect(el, callback){
17033
17236
  }, false)
17034
17237
  }
17035
17238
  function isIOSDevice() {
17036
- if (navigator.userAgentData && navigator.userAgentData.platform) {
17037
- if (navigator.userAgentData.platform === 'iOS') {
17038
- return true;
17039
- }
17040
- }
17041
- const userAgent = navigator.userAgent || navigator.vendor || window.opera;
17042
- const isIOS = /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream;
17043
- const isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 && !window.MSStream;
17044
- return isIOS || isIPadOS;
17239
+ return crouton.deviceType === "ios";
17045
17240
  }
17046
17241
 
17047
17242
  function isAndroidDevice() {
17048
- return /Android/i.test(navigator.userAgent);
17243
+ return crouton.deviceType === "android";
17049
17244
  }
17050
17245
 
17246
+
17051
17247
  function isMobileDevice() {
17052
17248
  return isIOSDevice() || isAndroidDevice() || /Mobi|Android/i.test(navigator.userAgent);
17053
17249
  }
@@ -17147,8 +17343,10 @@ function openDirectionsModal(e) {
17147
17343
 
17148
17344
  function closeDirectionsModal() {
17149
17345
  const modal = document.getElementById('directionsMapModal');
17150
- modal.style.display = 'none';
17151
- if (modal.className.includes('remove-after-use')) modal.remove();
17346
+ if (modal) {
17347
+ modal.style.display = 'none';
17348
+ if (modal.className.includes('remove-after-use')) modal.remove();
17349
+ }
17152
17350
  }
17153
17351
 
17154
17352
  function openDirections(url, latitude, longitude, fromModal = true) {
@@ -17171,33 +17369,31 @@ function MeetingMap(inConfig) {
17171
17369
  const config = inConfig;
17172
17370
  if (!config.maxZoom) config.maxZoom = 17;
17173
17371
  if (!config.minZoom) config.minZoom = 6;
17372
+ if (!config.locationSearchZoom) config.locationSearchZoom = 12; // TODO: for now, not in interface. Experience will show if it is worth adding to UI.
17174
17373
  if (!config.marker_contents_template) config.marker_contents_template = croutonDefaultTemplates.marker_contents_template;
17175
17374
  var gAllMeetings = [];
17176
17375
  var gMeetingIdsFromCrouton = null;
17177
17376
  var gSearchPoint = false;
17178
- var loadedCallbackFunction = null;
17179
- var loadedCallbackArgs = [];
17180
- var oldBounds = false;
17181
- var isMouseDown = false;
17377
+ var gLoadedCallbackFunction = null;
17378
+ var gLoadedCallbackArgs = [];
17379
+ var gOldBounds = false;
17380
+ var gCurrentlyDraggingMap = false;
17381
+ var gLocationSearchResult = null;
17182
17382
  function preloadApiLoadedCallback(f,a) {
17183
- loadedCallbackFunction = f;
17184
- loadedCallbackArgs = a;
17383
+ gLoadedCallbackFunction = f;
17384
+ gLoadedCallbackArgs = a;
17185
17385
  }
17186
17386
  function apiLoadedCallback() {
17187
- loadedCallbackFunction(...loadedCallbackArgs);
17387
+ gLoadedCallbackFunction(...gLoadedCallbackArgs);
17188
17388
  }
17189
-
17190
17389
  function retrieveGeolocation() {
17191
17390
  return new Promise((resolve, reject) => {
17192
- if (window.storedGeolocation) {
17193
- resolve(window.storedGeolocation);
17194
- } else if (navigator.geolocation) {
17391
+ if (navigator.geolocation) {
17195
17392
  navigator.geolocation.getCurrentPosition((position) => {
17196
- window.storedGeolocation = {
17197
- latitude: position.coords.latitude,
17198
- longitude: position.coords.longitude
17199
- };
17200
- resolve(window.storedGeolocation);
17393
+ resolve({
17394
+ lat: position.coords.latitude,
17395
+ lng: position.coords.longitude
17396
+ });
17201
17397
  }, (error) => {
17202
17398
  reject(new Error('Error getting geolocation: ' + error.message));
17203
17399
  });
@@ -17209,10 +17405,14 @@ function MeetingMap(inConfig) {
17209
17405
  function isFilterVisible() {
17210
17406
  return config.filter_visible && config.filter_visible == 1;
17211
17407
  }
17212
- /************************************************************************************//**
17213
- * \brief Load the map and set it up. *
17214
- ****************************************************************************************/
17215
-
17408
+ /**
17409
+ * Creates the map and adds the various ornaments like search buttons and menus.
17410
+ * @param HTMLElement inDiv Element that contains the map.
17411
+ * @param Object menuContext Contains info for the map menu. For instance, for [bmlt_map], the dropdown filters.
17412
+ * @param {*} handlebarMapOptions
17413
+ * @param Function cb
17414
+ * @param boolean hide
17415
+ */
17216
17416
  function loadMap(inDiv, menuContext, handlebarMapOptions=null,cb=null,hide=false) {
17217
17417
  if (inDiv) {
17218
17418
  crouton_Handlebars.registerPartial("markerContentsTemplate", crouton_Handlebars.compile(config['marker_contents_template']));
@@ -17239,8 +17439,8 @@ function MeetingMap(inConfig) {
17239
17439
  gDelegate.addListener('idle', triggerCroutonMapNewQuery, false);
17240
17440
  } else {
17241
17441
  gDelegate.addListener('zoomend', function (ev) {
17242
- if (shouldRedrawMarkers() && gAllMeetings) {
17243
- if (listOnlyVisible) {
17442
+ if (shouldRedrawMarkers() && gAllMeetings && !gLocationSearchResult) {
17443
+ if (gListOnlyVisible) {
17244
17444
  const oldValue = filterVisible(false);
17245
17445
  searchResponseCallback();
17246
17446
  filterVisible(oldValue);
@@ -17286,9 +17486,7 @@ function MeetingMap(inConfig) {
17286
17486
  controlDiv.querySelector("#bmltsearch-text-button").addEventListener('click', function () {
17287
17487
  let text = document.getElementById("bmltsearch-goto-text").value.trim();
17288
17488
  if (text === "") return;
17289
- showThrobber();
17290
- gDelegate.callGeocoder(text, null, mapSearchGeocode);
17291
- clearMessageAndClose(gSearchModal);
17489
+ gDelegate.callGeocoder(text, mapSearchGeocode);
17292
17490
  });
17293
17491
  controlDiv.querySelector("#modal-seach-parameters").style.display = 'none';
17294
17492
  controlDiv.querySelector("#show-search-parameters").addEventListener('click', function (e) {
@@ -17318,12 +17516,84 @@ function MeetingMap(inConfig) {
17318
17516
  });
17319
17517
 
17320
17518
  controlDiv.querySelector("#bmltsearch-clicksearch").addEventListener('click', clickSearch);
17321
- [...controlDiv.getElementsByClassName('modal-close')].forEach((elem)=>elem.addEventListener('click', (e)=>clearMessageAndClose(e.target)));
17519
+ [...controlDiv.getElementsByClassName('modal-close')].forEach((elem)=>elem.addEventListener('click', (e)=>closeModalWindow(e.target)));
17322
17520
  gSearchModal = controlDiv.querySelector("#bmltsearch_modal");
17323
17521
  gSearchModal.parentElement.removeChild(gSearchModal);
17324
17522
 
17325
17523
  return controlDiv;
17326
17524
  }
17525
+ var gLocationSearchModal;
17526
+ var gDefaultLocationSearchButtonLabel = '';
17527
+ function doGeolocationThenClose() {
17528
+ doGeolocation().then(closeModalWindow(gLocationSearchModal));
17529
+ }
17530
+ function createLocationSearchButton() {
17531
+ const template = hbs_Crouton.templates['locationSearch'];
17532
+ const controlDiv = document.createElement('div');
17533
+ const params = {};
17534
+ controlDiv.innerHTML = template(params);
17535
+ controlDiv.querySelector("#location-search-button").addEventListener('click', showLocationSearchDialog);
17536
+ gDefaultLocationSearchButtonLabel = controlDiv.querySelector("#location-search-button :first-child").innerHTML;
17537
+ controlDiv.querySelector("#bmlt-location-search-nearbyMeetings").addEventListener('click', doGeolocationThenClose);
17538
+ controlDiv.querySelector("#bmlt-location-search-goto-text").addEventListener('keypress', function (event) {
17539
+ if (event.key === "Enter") {
17540
+ event.preventDefault();
17541
+ document.getElementById("bmlt-location-search-text-button").click();
17542
+ }
17543
+ });
17544
+ controlDiv.querySelector("#bmlt-location-search-text-button").addEventListener('click', function () {
17545
+ let text = document.getElementById("bmlt-location-search-goto-text").value.trim();
17546
+ if (text === "") return;
17547
+ if (isMapVisible()) {
17548
+ gDelegate.callGeocoder(text, locationSearchOpenMapGeocode);
17549
+ } else {
17550
+ gDelegate.callGeocoder(text, locationSearchGeocode);
17551
+ }
17552
+ });
17553
+ controlDiv.querySelector("#bmlt-location-search-widen").addEventListener('click', function () {
17554
+ if (gLocationSearchResult === null) {
17555
+ if (gListOnlyVisible && gSearchPoint) {
17556
+ gLocationSearchResult = {center: gSearchPoint, bounds: gDelegate.getBounds(), zoom: gDelegate.getZoom()};
17557
+ } else return;
17558
+ }
17559
+ if (gLocationSearchResult.zoom == config.minZoom) return;
17560
+ filterVisible(false);
17561
+ let bounds = gDelegate.calculateBoundsFromCenterAndZoom(gLocationSearchResult.center, gLocationSearchResult.zoom);
17562
+ let knt = filterMeetingsAndBounds(bounds).length;
17563
+ for (let zoom = gLocationSearchResult.zoom-1; zoom >= config.minZoom; zoom = zoom-1) {
17564
+ bounds = gDelegate.calculateBoundsFromCenterAndZoom(gLocationSearchResult.center, zoom);
17565
+ if (filterMeetingsAndBounds(bounds).length > knt) {
17566
+ if (isMapVisible()) {
17567
+ gDelegate.flyToFixedZoom(gLocationSearchResult.center, zoom, filterVisible);
17568
+ gLocationSearchResult = null;
17569
+ } else {
17570
+ gLocationSearchResult.zoom = zoom;
17571
+ gLocationSearchResult.bounds = bounds;
17572
+ gListOnlyVisible = false; // force new calc.
17573
+ filterVisible(true, gLocationSearchResult.bounds);
17574
+ }
17575
+ closeModalWindow(gLocationSearchModal);
17576
+ return;
17577
+ }
17578
+ }
17579
+ bounds = gDelegate.calculateBoundsFromCenterAndZoom(gLocationSearchResult.center, gLocationSearchResult.zoom);
17580
+ filterVisible(true, bounds);
17581
+ alert("No further matches");
17582
+ });
17583
+ controlDiv.querySelector("#bmlt-location_search-cancel").addEventListener('click', function () {
17584
+ filterVisible(false);
17585
+ setLocationSearchButtonLabel('');
17586
+ closeModalWindow(gLocationSearchModal);
17587
+ });
17588
+ [...controlDiv.getElementsByClassName('modal-close')].forEach((elem)=>elem.addEventListener('click', (e)=>closeModalWindow(e.target)));
17589
+ gLocationSearchModal = controlDiv.querySelector("#bmlt_location_search_modal");
17590
+ gLocationSearchModal.parentElement.removeChild(gLocationSearchModal);
17591
+
17592
+ return controlDiv;
17593
+ }
17594
+ function isMapVisible() {
17595
+ return gDelegate.isMapVisible() && crouton.isEmbeddedMapShowing();
17596
+ }
17327
17597
  var next24status = false;
17328
17598
  function createNext24Toggle() {
17329
17599
  const toggleSrc = `
@@ -17349,14 +17619,14 @@ function MeetingMap(inConfig) {
17349
17619
  }`
17350
17620
  .replace("__text1__", crouton.localization.getWord("Upcoming Meetings"))
17351
17621
  .replace("__text2__", crouton.localization.getWord("All Meetings"));
17352
- var controlDiv = document.createElement('div');
17622
+ const controlDiv = document.createElement('div');
17353
17623
  controlDiv.innerHTML = toggleSrc;
17354
17624
  controlDiv.querySelector(".onoffswitch").addEventListener('click', function (event) {
17355
17625
  if (event.pointerId < 0) return;
17356
17626
  next24status = !next24status;
17357
- fitDuringFilter = false;
17627
+ gAllowExpandViewport = false;
17358
17628
  crouton.filterNext24(next24status);
17359
- fitDuringFilter = true;
17629
+ gAllowExpandViewport = true;
17360
17630
  });
17361
17631
  let style = document.createElement('style');
17362
17632
  style.innerHTML = rules;
@@ -17364,15 +17634,18 @@ function MeetingMap(inConfig) {
17364
17634
  return controlDiv;
17365
17635
  }
17366
17636
  function createMenuButton(menuContext) {
17367
- var template = hbs_Crouton.templates['mapMenu'];
17368
- var controlDiv = document.createElement('div');
17637
+ const template = hbs_Crouton.templates['mapMenu'];
17638
+ const controlDiv = document.createElement('div');
17369
17639
  controlDiv.innerHTML = template(menuContext);
17370
17640
  controlDiv.querySelector("#nearbyMeetings").addEventListener('click', function (e) {
17371
17641
  retrieveGeolocation().then(position => {
17372
17642
  filterVisible(false);
17373
- gDelegate.setViewToPosition(position, filterMeetingsAndBounds, filterVisible);
17374
- gSearchPoint = {"lat": position.latitude, "lng": position.longitude};
17643
+ gSearchPoint = {"lat": position.lat, "lng": position.lng};
17375
17644
  crouton.updateDistances();
17645
+ const locationSearchResult = gDelegate.getZoomAdjustedBounds(gSearchPoint, filterMeetingsAndBounds, config.locationSearchZoom ?? 12);
17646
+ gDelegate.flyToFixedZoom(position, locationSearchResult.zoom, filterVisible);
17647
+ filterVisible(true);
17648
+ setLocationSearchButtonLabel(crouton.localization.getWord('closest meetings'));
17376
17649
 
17377
17650
  }).catch(error => {
17378
17651
  console.log(error.message);
@@ -17394,7 +17667,7 @@ function MeetingMap(inConfig) {
17394
17667
  if (dropdownContent.style.display == "inline-block") {
17395
17668
  dropdownContent.style.display = "none";
17396
17669
  } else {
17397
- jQuery("#filteringByVisibility").html(listOnlyVisible?'&#10004;':'');
17670
+ jQuery("#filteringByVisibility").html(gListOnlyVisible?'&#10004;':'');
17398
17671
  dropdownContent.style.display = "inline-block";
17399
17672
  }
17400
17673
  });
@@ -17402,13 +17675,11 @@ function MeetingMap(inConfig) {
17402
17675
  controlDiv.querySelector("#close_table").addEventListener('click', hideListView);
17403
17676
  controlDiv.querySelector("#goto-text").addEventListener('keydown', function (event) {
17404
17677
  if (event && event.key == "Enter") {
17405
- closeModalWindow(event.target);
17406
- lookupLocation(g_suspendedFullscreen);
17678
+ lookupLocation(document.getElementById('goto-text').value,g_suspendedFullscreen, mapMenuGeocode);
17407
17679
  }
17408
17680
  });
17409
17681
  controlDiv.querySelector("#goto-button").addEventListener('click', function (event) {
17410
- closeModalWindow(event.target);
17411
- lookupLocation(g_suspendedFullscreen);
17682
+ lookupLocation(document.getElementById('goto-text').value, g_suspendedFullscreen, mapMenuGeocode);
17412
17683
  });
17413
17684
 
17414
17685
  return controlDiv;
@@ -17416,6 +17687,17 @@ function MeetingMap(inConfig) {
17416
17687
  function hasMapSearch() {
17417
17688
  return 'map_search' in config;
17418
17689
  }
17690
+ /**
17691
+ * Load the meetings for [bmlt_tabs] and [bmlt_map]: all the meetings, during map initialization.
17692
+ * @param string inDiv_id selector for the div that will contain the map.
17693
+ * @param Array meetings_responseObject the meetings returned from the server and enhanced by the crouton core.
17694
+ * @param {*} menuContext information about the dropdown filters.
17695
+ * @param {*} handlebarMapOptions
17696
+ * @param boolean fitBounds should we expand our map so that all the meetings are visible?
17697
+ * @param function callback called after map has been initialized
17698
+ * @param boolean hide make the map invisisble
17699
+ * @returns
17700
+ */
17419
17701
  function loadFromCrouton(inDiv_id, meetings_responseObject, menuContext = null, handlebarMapOptions = null, fitBounds = true, callback, hide) {
17420
17702
  if (!gDelegate.isApiLoaded()) {
17421
17703
  preloadApiLoadedCallback(loadFromCrouton, [inDiv_id, meetings_responseObject, menuContext, handlebarMapOptions, fitBounds, callback, hide]);
@@ -17424,8 +17706,15 @@ function MeetingMap(inConfig) {
17424
17706
  }
17425
17707
  let inDiv = document.getElementById(inDiv_id);
17426
17708
  loadMap(inDiv, menuContext, handlebarMapOptions, callback, hide);
17427
- loadAllMeetings(meetings_responseObject, fitBounds, true);
17709
+ loadAllMeetings(meetings_responseObject, fitBounds);
17428
17710
  };
17711
+ /**
17712
+ * The map on the meeting details popup modal.
17713
+ * @param string inDiv_id selector for the div that will contain the map.
17714
+ * @param Object meeting
17715
+ * @param {*} handlebarMapOptions
17716
+ * @returns
17717
+ */
17429
17718
  function loadPopupMap(inDiv_id, meeting, handlebarMapOptions = null) {
17430
17719
  if (!gDelegate.isApiLoaded()) {
17431
17720
  preloadApiLoadedCallback(loadPopupMap, [inDiv_id, meeting, handlebarMapOptions]);
@@ -17443,25 +17732,21 @@ function MeetingMap(inConfig) {
17443
17732
  gModalDelegate = delegate;
17444
17733
  }
17445
17734
  };
17446
- var fitDuringFilter = true;
17447
- function filterFromCrouton(filter) {
17448
- gMeetingIdsFromCrouton = filter;
17735
+ var gAllowExpandViewport = true;
17736
+ function setFilteredIds(ids) {
17737
+ gMeetingIdsFromCrouton = ids;
17449
17738
  if (gAllMeetings)
17450
- searchResponseCallback(fitDuringFilter && !listOnlyVisible);
17739
+ searchResponseCallback(gAllowExpandViewport && !gListOnlyVisible);
17451
17740
  };
17452
- function clearMessageAndClose(modal) {
17453
- jQuery('#zoomed-out-message').not('.hide').addClass('hide');
17454
- closeModalWindow(modal);
17455
- }
17456
17741
  function nearMeSearch() {
17457
17742
  retrieveGeolocation().then(position => {
17458
17743
  showThrobber();
17459
- gSearchPoint = {"lat": position.latitude, "lng": position.longitude};
17460
- crouton.searchByCoordinates(position.latitude, position.longitude, config.map_search.width);
17461
- if (activeModal == gSearchModal) clearMessageAndClose(gSearchModal);
17744
+ gSearchPoint = {"lat": position.lat, "lng": position.lng};
17745
+ crouton.searchByCoordinates(position.lat, position.lng, config.map_search.width);
17746
+ if (gActiveModal == gSearchModal) closeModalWindow(gSearchModal);
17462
17747
  }).catch(error => {
17463
17748
  console.log(error.message);
17464
- if (activeModal != gSearchModal) showBmltSearchDialog();
17749
+ if (gActiveModal != gSearchModal) showBmltSearchDialog();
17465
17750
  });
17466
17751
  };
17467
17752
  function clickSearch(e) {
@@ -17471,7 +17756,7 @@ function MeetingMap(inConfig) {
17471
17756
  gSearchPoint = {"lat": lat, "lng": lng};
17472
17757
  crouton.searchByCoordinates(lat, lng, config.map_search.width);
17473
17758
  });
17474
- clearMessageAndClose(gSearchModal);
17759
+ closeModalWindow(gSearchModal);
17475
17760
  }
17476
17761
  function createThrobber(inDiv) {
17477
17762
  if (!inDiv.myThrobber) {
@@ -17481,7 +17766,7 @@ function MeetingMap(inConfig) {
17481
17766
  inDiv.myThrobber.className = 'bmlt_map_throbber_div';
17482
17767
  inDiv.myThrobber.style.display = 'none';
17483
17768
  inDiv.appendChild(inDiv.myThrobber);
17484
- var img = document.createElement("img");
17769
+ const img = document.createElement("img");
17485
17770
 
17486
17771
  if (img) {
17487
17772
  img.src = config.BMLTPlugin_images ? config.BMLTPlugin_images + "/Throbber.gif"
@@ -17506,19 +17791,104 @@ function MeetingMap(inConfig) {
17506
17791
  gInDiv.myThrobber.style.display = 'none';
17507
17792
  };
17508
17793
  };
17794
+ function setLocationSearchButtonLabel(label) {
17795
+ if (!label || label==='')
17796
+ jQuery("#location-search-button :first-child").html(gDefaultLocationSearchButtonLabel);
17797
+ else if (gDefaultLocationSearchButtonLabel && gDefaultLocationSearchButtonLabel !== '') {
17798
+ let html = gDefaultLocationSearchButtonLabel.replace(crouton.localization.getWord("Search by Location"), label);
17799
+ jQuery("#location-search-button :first-child").html(html);
17800
+ }
17801
+ }
17802
+ function openMapGeocode(resp, modalName, initial=false) {
17803
+ chooseResponse(modalName, resp, function(resp, i) {
17804
+ let center = gDelegate.getGeocodeCenterAndBounds(resp,i).center;
17805
+ gSearchPoint = {"lat": center.lat, "lng": center.lng};
17806
+ crouton.updateDistances(initial);
17807
+ const modal = document.getElementById(modalName);
17808
+ closeModalWindow(modal);
17809
+ filterVisible(false);
17810
+ const centerAndBounds = gDelegate.getGeocodeCenterAndBounds(resp, i);
17811
+ if (!centerAndBounds) return;
17812
+ const zoom = calcZoomThatContainsBoundingBox(centerAndBounds);
17813
+ const locationSearchResult = gDelegate.getZoomAdjustedBounds(gSearchPoint, filterMeetingsAndBounds, zoom);
17814
+ gDelegate.flyToFixedZoom(gSearchPoint, locationSearchResult.zoom, filterVisible);
17815
+ searchResponseCallback();
17816
+ })
17817
+ }
17818
+ function mapMenuGeocode(resp) {
17819
+ openMapGeocode(resp, "geocoding_modal");
17820
+ }
17821
+ function mapMenuGeocodeInitial(resp) {
17822
+ openMapGeocode(resp, "geocoding_modal", true);
17823
+ }
17509
17824
  function mapSearchGeocode(resp) {
17510
- showThrobber();
17511
- if (document.getElementById("bmltsearch-goto-text"))
17512
- document.getElementById("bmltsearch-goto-text").value = "";
17513
- let latlng = gDelegate.getGeocodeCenter(resp);
17514
- if (!latlng) {
17515
- hideThrobber();
17825
+ chooseResponse('bmltsearch_modal', resp, function(resp, i) {
17826
+ closeModalWindow(gSearchModal);
17827
+ if (document.getElementById("bmltsearch-goto-text"))
17828
+ document.getElementById("bmltsearch-goto-text").value = "";
17829
+ let latlng = gDelegate.getGeocodeCenterAndBounds(resp,i).center;
17830
+ if (!latlng) return;
17831
+ showThrobber();
17832
+ gSearchPoint = {"lat": latlng.lat, "lng": latlng.lng};
17833
+ crouton.searchByCoordinates(latlng.lat, latlng.lng, config.map_search.width);
17834
+ });
17835
+ }
17836
+ function chooseResponse(modalName, resp, callback) {
17837
+ if (jQuery('#'+modalName).is(":hidden")) {
17838
+ callback(resp, 0);
17839
+ return;
17840
+ }
17841
+ const choices = gDelegate.getGeocodingChoices(resp);
17842
+ if (choices.length < 2) {
17843
+ setLocationSearchButtonLabel(choices[0]);
17844
+ callback(resp, 0);
17516
17845
  return;
17517
17846
  }
17518
- gSearchPoint = {"lat": latlng.lat, "lng": latlng.lng};
17519
- crouton.searchByCoordinates(latlng.lat, latlng.lng, config.map_search.width);
17847
+ const html = choices.map((choice, index) =>
17848
+ '<button class="location-choice" data-choice="'+index+'">'+choice+'</button>'
17849
+ );
17850
+ jQuery('#'+modalName+' .crouton-modal-search-page').addClass('hide');
17851
+ jQuery('#'+modalName+' .crouton-modal-search-choice').removeClass('hide')
17852
+ .html('<div class="choose-location"><h4>'+crouton.localization.getWord('Choose one')+'</h4>'+html.join('')+'</div>')
17853
+ jQuery('#'+modalName+' .location-choice').on('click', function() {
17854
+ const index = parseInt(jQuery(this).data("choice"))
17855
+ setLocationSearchButtonLabel(choices[index]);
17856
+ callback(resp, index);
17857
+ })
17858
+ }
17859
+ function locationSearchOpenMapGeocode(resp) {
17860
+ openMapGeocode(resp, 'bmlt_location_search_modal');
17861
+ }
17862
+ function calcZoomThatContainsBoundingBox(centerAndBounds) {
17863
+ const center = {lat: (centerAndBounds.southWest.lat + centerAndBounds.northEast.lat)/2,
17864
+ lng: (centerAndBounds.southWest.lng + centerAndBounds.northEast.lng)/2,};
17865
+ let zoom = config.locationSearchZoom + 1;
17866
+ do {
17867
+ if (zoom <= config.minZoom) break;
17868
+ zoom = zoom - 1;
17869
+ var bounds = gDelegate.calculateBoundsFromCenterAndZoom(center, zoom);
17870
+ } while (!gDelegate.contains(bounds, centerAndBounds.southWest.lat, centerAndBounds.southWest.lng)
17871
+ || !gDelegate.contains(bounds, centerAndBounds.northEast.lat, centerAndBounds.northEast.lng))
17872
+ return zoom;
17873
+ }
17874
+ function locationSearchGeocodeInitial(resp) {
17875
+ locationSearchGeocode(resp, true);
17876
+ }
17877
+ function locationSearchGeocode(resp, initial=false) {
17878
+ chooseResponse('bmlt_location_search_modal', resp, function(resp, i) {
17879
+ closeModalWindow(gLocationSearchModal);
17880
+ const centerAndBounds = gDelegate.getGeocodeCenterAndBounds(resp, i);
17881
+ if (!centerAndBounds) return;
17882
+ let center = centerAndBounds.center;
17883
+ filterVisible(false);
17884
+ let zoom = calcZoomThatContainsBoundingBox(centerAndBounds);
17885
+ gLocationSearchResult = gDelegate.getZoomAdjustedBounds(center, filterMeetingsAndBounds, zoom);
17886
+ gSearchPoint = {"lat": gLocationSearchResult.center.lat, "lng": gLocationSearchResult.center.lng};
17887
+ filterVisible(true, gLocationSearchResult.bounds);
17888
+ crouton.updateDistances(initial);
17889
+ });
17520
17890
  }
17521
- function loadAllMeetings(meetings_responseObject, fitBounds=true, fitAll=false) {
17891
+ function loadAllMeetings(meetings_responseObject, fitBounds=true) {
17522
17892
  if (meetings_responseObject === null && config.map_search) {
17523
17893
  if (config.map_search.auto) nearMeSearch();
17524
17894
  else if (config.map_search.coordinates_search) {
@@ -17527,12 +17897,12 @@ function MeetingMap(inConfig) {
17527
17897
  gSearchPoint = {"lat": config.map_search.latitude, "lng": config.map_search.longitude};
17528
17898
  crouton.searchByCoordinates(config.map_search.latitude, config.map_search.longitude, config.map_search.width);
17529
17899
  }
17530
- else if (config.map_search.location) gDelegate.callGeocoder(config.map_search.location, null, mapSearchGeocode);
17900
+ else if (config.map_search.location) gDelegate.callGeocoder(config.map_search.location, mapSearchGeocode);
17531
17901
  else showBmltSearchDialog();
17532
17902
  return;
17533
17903
  }
17534
17904
  gAllMeetings = meetings_responseObject.filter(m => m.venue_type != 2);
17535
- if (fitBounds) {
17905
+ if (fitBounds && !config.centerMe && !config.goto) {
17536
17906
  let lat_lngs = gAllMeetings.reduce(function(a,m) {a.push([m.latitude, m.longitude]); return a;},[]);
17537
17907
  const maxRadius = config.maxTomatoWidth/2.0;
17538
17908
  if (gSearchPoint) lat_lngs.push([gSearchPoint.lat, gSearchPoint.lng]);
@@ -17548,31 +17918,45 @@ function MeetingMap(inConfig) {
17548
17918
  }
17549
17919
  searchResponseCallback();
17550
17920
  hideThrobber();
17551
- if (isFilterVisible() || config.centerMe || config.goto) crouton.forceShowMap();
17552
- if (config.centerMe) {
17553
- if (navigator.geolocation) {
17554
- navigator.geolocation.getCurrentPosition(
17555
- function (position) {
17556
- coords = {latitude: position.coords.latitude, longitude: position.coords.longitude};
17557
- filterVisible(false);
17558
- if (config.zoom) gDelegate.setZoom(false, config.zoom);
17559
- gDelegate.setViewToPosition(coords, filterMeetingsAndBounds, () => {
17560
- filterVisible(isFilterVisible());
17561
- });
17562
- gSearchPoint = {"lat": position.coords.latitude, "lng": position.coords.longitude};
17563
- crouton.updateDistances(true);
17564
- },
17565
- showGeocodingDialog
17566
- );
17567
- } else if (fitAll) {
17568
- showGeocodingDialog();
17569
- }
17570
- } else {
17571
- if ((!config.centerMe && !config.goto) && !(config.map_search && isFilterVisible())) {
17572
- gDelegate.afterInit(()=>filterVisible(isFilterVisible()));
17921
+ gDelegate.afterInit(!crouton.isEmbeddedMapShowing(), () => {
17922
+ if (config.centerMe) {
17923
+ doGeolocation(isFilterVisible(), true).catch(error => showGeocodingDialog());
17924
+ } else {
17925
+ if ((!config.centerMe && !config.goto) && !(config.map_search && isFilterVisible())) {
17926
+ filterVisible(isFilterVisible());
17927
+ }
17928
+ if (config.goto) {
17929
+ if (isMapVisible()) {
17930
+ gDelegate.callGeocoder(config.goto, mapMenuGeocodeInitial);
17931
+ } else {
17932
+ gDelegate.callGeocoder(config.goto, locationSearchGeocodeInitial);
17933
+ }
17934
+ }
17573
17935
  }
17574
- if (config.goto) gDelegate.callGeocoder(config.goto, isFilterVisible() ? resetVisibleThenFilterMeetingsAndBounds : setVisibleThenFilterMeetingsAndBounds);
17575
- }
17936
+ });
17937
+ }
17938
+ function doGeolocation(makeFilterVisible=true, initial=false) {
17939
+ return new Promise((resolve, reject) =>
17940
+ retrieveGeolocation().then(function(coords) {
17941
+ filterVisible(false);
17942
+ if (isMapVisible() || !makeFilterVisible) {
17943
+ const locationSearchResult = gDelegate.getZoomAdjustedBounds(coords, filterMeetingsAndBounds, config.locationSearchZoom ?? 12);
17944
+ gDelegate.flyToFixedZoom(coords, locationSearchResult.zoom, () => {
17945
+ filterVisible(makeFilterVisible);
17946
+ if (makeFilterVisible) setLocationSearchButtonLabel(crouton.localization.getWord('closest meetings'));
17947
+ });
17948
+ } else {
17949
+ gLocationSearchResult = gDelegate.getZoomAdjustedBounds(coords, filterMeetingsAndBounds, config.locationSearchZoom ?? 12);
17950
+ filterVisible(true, gLocationSearchResult.bounds);
17951
+ setLocationSearchButtonLabel(crouton.localization.getWord('closest meetings'));
17952
+ }
17953
+ gSearchPoint = coords;
17954
+ crouton.updateDistances(initial);
17955
+ resolve(coords);
17956
+ }).catch(error => {
17957
+ reject(error);
17958
+ })
17959
+ );
17576
17960
  }
17577
17961
  function createCityHash(allMeetings) {
17578
17962
  return allMeetings.reduce(function(prev, meeting) {
@@ -17585,11 +17969,12 @@ function MeetingMap(inConfig) {
17585
17969
  }
17586
17970
  var g_suspendedFullscreen = false;
17587
17971
  var g_overflowX;
17588
- var activeModal = null;
17972
+ var gActiveModal = null;
17589
17973
  var swipableModal = false;
17590
17974
  function closeModalWindow(modal) {
17591
17975
  gDelegate.modalOff();
17592
- activeModal = null;
17976
+ gActiveModal = null;
17977
+ if (!modal) return;
17593
17978
  if (!modal.classList.contains("modal"))
17594
17979
  return closeModalWindow(modal.parentNode);
17595
17980
  modal.style.display = "none";
@@ -17609,8 +17994,8 @@ function MeetingMap(inConfig) {
17609
17994
  }
17610
17995
  }
17611
17996
  document.addEventListener("keydown", function(event) {
17612
- if (activeModal && event.key == "Escape") {
17613
- closeModalWindow(activeModal);
17997
+ if (gActiveModal && event.key == "Escape") {
17998
+ closeModalWindow(gActiveModal);
17614
17999
  }
17615
18000
  }, true);
17616
18001
  function openModalWindow(modal,swipe=false) {
@@ -17620,9 +18005,10 @@ function MeetingMap(inConfig) {
17620
18005
  }
17621
18006
  if (!modal) return;
17622
18007
  modal.style.display = "block";
18008
+ document.body.appendChild(modal);
17623
18009
  swipableModal = swipe;
17624
18010
  modal.focus();
17625
- activeModal = modal;
18011
+ gActiveModal = modal;
17626
18012
  dd = document.getElementById("map-menu-dropdown");
17627
18013
  if (dd) dd.style.display = "none";
17628
18014
  gDelegate.modalOn();
@@ -17640,15 +18026,30 @@ function MeetingMap(inConfig) {
17640
18026
  openModalWindow(document.getElementById('filter_modal'));
17641
18027
  }
17642
18028
  function showBmltSearchDialog(e) {
17643
- if (!document.getElementById('bmltsearch_modal')) gInDiv.appendChild(gSearchModal);
18029
+ openModalWindow(gSearchModal);
17644
18030
  if (gDelegate.isMapDefined())
17645
18031
  jQuery('#bmltsearch-clicksearch').parent().show();
17646
18032
  else
17647
18033
  jQuery('#bmltsearch-clicksearch').parent().hide();
17648
- openModalWindow(gSearchModal);
18034
+ jQuery('#zoomed-out-message').addClass('hide');
18035
+ jQuery('#bmltsearch_modal .crouton-modal-search-page').removeClass('hide');
18036
+ jQuery('#bmltsearch_modal .crouton-modal-search-choice').addClass('hide');
18037
+ }
18038
+ function showLocationSearchDialog(e) {
18039
+ openModalWindow(gLocationSearchModal);
18040
+ if ((gSearchPoint !== null) && gListOnlyVisible) {
18041
+ jQuery("#location-search-widen").removeClass('hide');
18042
+ } else {
18043
+ jQuery("#location-search-widen").addClass('hide');
18044
+ }
18045
+ jQuery('#bmlt_location_search_modal .crouton-modal-search-page').removeClass('hide');
18046
+ jQuery('#bmlt_location_search_modal .crouton-modal-search-choice').addClass('hide');
18047
+ jQuery('bmlt-location-search-goto-text').val('');
17649
18048
  }
17650
18049
  function showGeocodingDialog(e=null) {
17651
18050
  openModalWindow(document.getElementById('geocoding_modal'));
18051
+ jQuery('#geocoding_modal .crouton-modal-search-page').removeClass('hide');
18052
+ jQuery('#geocoding_modal .crouton-modal-search-choice').addClass('hide');
17652
18053
  }
17653
18054
  function showListView(e=null) {
17654
18055
  filterVisible();
@@ -17664,36 +18065,17 @@ function MeetingMap(inConfig) {
17664
18065
  jQuery("#table_page").addClass("hide");
17665
18066
  jQuery("#bmlt-map").css("display", "block");
17666
18067
  }
17667
- function resetVisibleThenFilterMeetingsAndBounds(bounds, center=null) {
17668
- filterVisible(false);
17669
- const ret = filterMeetingsAndBounds(bounds);
17670
- filterVisible(true);
17671
- if (gSearchPoint.lat != center.lat || gSearchPoint.lng != center.lng) {
17672
- gSearchPoint = center;
17673
- crouton.updateDistances();
17674
- }
17675
- return ret;
17676
- }
17677
- function setVisibleThenFilterMeetingsAndBounds(bounds, center=null) {
17678
- filterVisible(false);
17679
- const ret = filterMeetingsAndBounds(bounds);
17680
- if (gSearchPoint.lat != center.lat || gSearchPoint.lng != center.lng) {
17681
- gSearchPoint = center;
17682
- crouton.updateDistances();
17683
- }
17684
- return ret;
17685
- }
17686
- function lookupLocation(fullscreen) {
17687
- if (document.getElementById('goto-text').value != '') {
18068
+ function lookupLocation(location,fullscreen, callback) {
18069
+ if (location != '') {
17688
18070
  if (fullscreen) {
17689
18071
  gDelegate.addListener('idle', function () {
17690
- gDelegate.callGeocoder(document.getElementById('goto-text').value, resetVisibleThenFilterMeetingsAndBounds);
18072
+ gDelegate.callGeocoder(location, callback);
17691
18073
  }, true);
17692
18074
  } else {
17693
- gDelegate.callGeocoder(document.getElementById('goto-text').value, resetVisibleThenFilterMeetingsAndBounds);
18075
+ gDelegate.callGeocoder(location, callback);
17694
18076
  }
17695
18077
  } else {
17696
- alert("");
18078
+ alert("Location not found");
17697
18079
  };
17698
18080
  return true;
17699
18081
  };
@@ -17701,19 +18083,9 @@ function MeetingMap(inConfig) {
17701
18083
  if (!gAllMeetings || !gAllMeetings.length) {
17702
18084
  return;
17703
18085
  };
17704
- try {
17705
- drawMarkers(expand);
17706
- if (gSearchPoint) {
17707
- gDelegate.markSearchPoint([gSearchPoint.lat, gSearchPoint.lng]);
17708
- }
17709
- } catch (e) {
17710
- console.log(e);
17711
- gDelegate.addListener('projection_changed', function (ev) {
17712
- drawMarkers(expand);
17713
- if (gSearchPoint) {
17714
- gDelegate.markSearchPoint([gSearchPoint.lat, gSearchPoint.lng]);
17715
- }
17716
- }, true);
18086
+ drawMarkers(expand);
18087
+ if (gSearchPoint) {
18088
+ gDelegate.markSearchPoint([gSearchPoint.lat, gSearchPoint.lng]);
17717
18089
  }
17718
18090
  };
17719
18091
  /****************************************************************************************
@@ -17761,33 +18133,55 @@ function MeetingMap(inConfig) {
17761
18133
  gDelegate.fitBounds(lat_lngs);
17762
18134
  }
17763
18135
  };
18136
+ function latLngToWebMercator(latlng, zoom) {
18137
+ const lat = Math.max(-85.05112878, Math.min(85.05112878, latlng.lat));
18138
+ const phi = lat * Math.PI / 180;
18139
+ const scale = 256 * Math.pow(2, zoom);
18140
+
18141
+ const x = scale * ((latlng.lng/360.) + .5);
18142
+ const y =
18143
+ scale * (Math.PI - Math.log(Math.tan(Math.PI / 4 + phi / 2))) / (2 * Math.PI);
18144
+ return { x: x, y: y };
18145
+ }
18146
+ function webMercatorToLatLng(point, zoom) {
18147
+ const scale = 256 * Math.pow(2, zoom);
18148
+
18149
+ const lng = 360 * (point.x / scale - .5);
18150
+ const t = Math.exp(Math.PI - (2 * Math.PI) * (point.y / scale));
18151
+ const phi = 2 * Math.atan(t) - Math.PI / 2; // radians
18152
+
18153
+ return { lat: phi * 180 / Math.PI, lng: lng };
18154
+ }
17764
18155
  function mapOverlappingMarkersInCity(in_meeting_array) ///< Used to draw the markers when done.
17765
18156
  {
17766
- var tolerance = 8; /* This is how many pixels we allow. */
18157
+ const tolerance = 8; /* This is how many pixels we allow. */
17767
18158
 
17768
- var ret = new Array;
18159
+ const ret = new Array;
18160
+ const zoom = gDelegate.getZoom();
18161
+ const center = latLngToWebMercator(gDelegate.getCenter(), zoom)
17769
18162
  // We create this hash because we limit looking for "matches" to within one city.
17770
18163
  for (const [city, meetings] of Object.entries(createCityHash(in_meeting_array))) {
17771
18164
  // create a tmp object so we can mark which items haven't been matched yet.
17772
- var tmp = meetings.map((meeting) => {
18165
+ const tmp = meetings.map((meeting) => {
17773
18166
  item = new Object;
17774
18167
  item.matched = false;
17775
18168
  item.meeting = meeting;
17776
- item.coords = gDelegate.fromLatLngToPoint(meeting.latitude, meeting.longitude);
18169
+ const point = latLngToWebMercator({lat: meeting.latitude, lng: meeting.longitude}, zoom);
18170
+ item.coords = {x: point.x-center.x, y: point.y-center.y};
17777
18171
  return item;
17778
18172
  });
17779
18173
  tmp.reduce(function(prev, item, index) {
17780
18174
  if (item.matched) return prev;
17781
18175
  matches = [item.meeting];
17782
- var outer_coords = item.coords;
18176
+ const outer_coords = item.coords;
17783
18177
  for (c2 = index+1; c2<meetings.length; c2++) {
17784
18178
  if (tmp[c2].matched) continue;
17785
- var inner_coords = tmp[c2].coords;
18179
+ const inner_coords = tmp[c2].coords;
17786
18180
 
17787
- var xmin = outer_coords.x - tolerance;
17788
- var xmax = outer_coords.x + tolerance;
17789
- var ymin = outer_coords.y - tolerance;
17790
- var ymax = outer_coords.y + tolerance;
18181
+ const xmin = outer_coords.x - tolerance;
18182
+ const xmax = outer_coords.x + tolerance;
18183
+ const ymin = outer_coords.y - tolerance;
18184
+ const ymax = outer_coords.y + tolerance;
17791
18185
 
17792
18186
  /* We have an overlap. */
17793
18187
  if ((inner_coords.x >= xmin) && (inner_coords.x <= xmax) && (inner_coords.y >= ymin) && (inner_coords.y <= ymax)) {
@@ -17804,8 +18198,8 @@ function MeetingMap(inConfig) {
17804
18198
  return ret;
17805
18199
  };
17806
18200
  function sortMeetingSearchResponseCallback(mtg_a, mtg_b) {
17807
- var weekday_score_a = parseInt(mtg_a.weekday_tinyint, 10);
17808
- var weekday_score_b = parseInt(mtg_b.weekday_tinyint, 10);
18201
+ const weekday_score_a = parseInt(mtg_a.weekday_tinyint, 10);
18202
+ const weekday_score_b = parseInt(mtg_b.weekday_tinyint, 10);
17809
18203
 
17810
18204
  if (weekday_score_a < config.start_week) {
17811
18205
  weekday_score_a += 7;
@@ -17821,8 +18215,8 @@ function MeetingMap(inConfig) {
17821
18215
  else if (weekday_score_a > weekday_score_b) {
17822
18216
  return 1;
17823
18217
  };
17824
- var time_a = mtg_a.start_time.toString().split(':');
17825
- var time_b = mtg_b.start_time.toString().split(':');
18218
+ const time_a = mtg_a.start_time.toString().split(':');
18219
+ const time_b = mtg_b.start_time.toString().split(':');
17826
18220
  if (parseInt(time_a[0]) < parseInt(time_b[0])) {
17827
18221
  return -1;
17828
18222
  }
@@ -17854,77 +18248,77 @@ function MeetingMap(inConfig) {
17854
18248
  * \brief This creates a single meeting's marker on the map. *
17855
18249
  ****************************************************************************************/
17856
18250
  function createMapMarker(meetings, openMarker) {
17857
- var main_point = [meetings[0].latitude, meetings[0].longitude];
18251
+ const main_point = [meetings[0].latitude, meetings[0].longitude];
17858
18252
  const marker_html = markerTemplate(meetings);
17859
18253
  const marker = gDelegate.createMarker(main_point, (meetings.length > 1), null);
17860
18254
  gDelegate.bindPopup(marker, marker_html, meetings.map((m)=>parseInt(m.id_bigint)), openMarker);
17861
18255
  };
17862
18256
  function createGroupMarker(group, openMarker) {
17863
- var main_point = [group.latitude, group.longitude];
18257
+ const main_point = [group.latitude, group.longitude];
17864
18258
  const marker = gDelegate.createMarker(main_point, group['membersOfGroup'].length > 1, null);
17865
18259
  gDelegate.addMarkerCallback(marker, function() {
17866
18260
  crouton.openMeetingModal(group);
17867
18261
  });
17868
18262
  };
17869
- var listOnlyVisible = false;
17870
- var listener = null;
18263
+ var gListOnlyVisible = false;
18264
+ var gDragStartListener = null;
17871
18265
  function filterBounds(bounds) {
17872
18266
  return gAllMeetings.filter((meeting) => gDelegate.contains(bounds, meeting.latitude, meeting.longitude));
17873
18267
  }
17874
18268
  function onDragStart() {
17875
- isMouseDown = true;
18269
+ gCurrentlyDraggingMap = true;
17876
18270
  // if no [crouton_map], then show all meetings
17877
18271
  if (!config.map_search) filterVisible(false);
17878
18272
  gDelegate.addListener('dragend', onDragEnd, true);
17879
18273
  }
17880
18274
  function onDragEnd() {
17881
- isMouseDown = false;
18275
+ gCurrentlyDraggingMap = false;
17882
18276
  // if no [crouton_map], then turn filter visible back on.
17883
18277
  if (config.map_search && isFilterVisible()) triggerCroutonMapNewQuery(null);
17884
18278
  else filterVisible(true);
17885
18279
  }
17886
18280
  function triggerCroutonMapNewQuery(ev) {
17887
- if (isMouseDown) return;
18281
+ if (gCurrentlyDraggingMap) return;
17888
18282
  gMeetingIdsFromCrouton = null;
17889
18283
  corners = gDelegate.getCorners();
17890
- if (oldBounds && gDelegate.contains(oldBounds,corners.ne.lat,corners.ne.lng)
17891
- && gDelegate.contains(oldBounds,corners.sw.lat,corners.sw.lng)) {
18284
+ if (gOldBounds && gDelegate.contains(gOldBounds,corners.ne.lat,corners.ne.lng)
18285
+ && gDelegate.contains(gOldBounds,corners.sw.lat,corners.sw.lng)) {
17892
18286
  filterVisible();
17893
18287
  } else if (getScreenRadius('km') > config.maxTomatoWidth) {
17894
18288
  jQuery('#zoomed-out-message').removeClass('hide');
17895
18289
  showBmltSearchDialog(null);
17896
18290
  } else {
17897
- oldBounds = gDelegate.getBounds();
18291
+ gOldBounds = gDelegate.getBounds();
17898
18292
  showThrobber();
17899
18293
  crouton.searchByCoordinates(gDelegate.getCenter().lat, gDelegate.getCenter().lng, getScreenRadius(), false);
17900
18294
  }
17901
18295
  }
17902
- function filterVisible(on=true) {
17903
- if (on==listOnlyVisible && !config.map_search) return on;
17904
- let mtgs = on ? filterBounds(gDelegate.getBounds()) : gAllMeetings;
18296
+ function filterVisible(on=true, bounds = gDelegate.getBounds()) {
18297
+ if (on==gListOnlyVisible && !config.map_search) return on;
18298
+ let mtgs = on ? filterBounds(bounds) : gAllMeetings;
17905
18299
  let visible = mtgs.map((m)=>m.id_bigint);
17906
18300
  jQuery(".bmlt-data-row").each(function(index,row) {
17907
18301
  row.dataset.visible = (visible.includes(row.id.split('-').pop())) ? '1' : '0';
17908
18302
  });
17909
18303
  jQuery("#byday").removeClass('hide');
17910
18304
  jQuery("#filter-dropdown-visibile").val(on?'a-1':'');
17911
- fitDuringFilter = false;
17912
- crouton.simulateFilterDropdown();
17913
- fitDuringFilter = true;
18305
+ gAllowExpandViewport = false; // calling simulateFilterDropdown will callback croutonMap to set the filtered Ids.
18306
+ crouton.simulateFilterDropdown(); // but we don't want to expand the viewport.
18307
+ gAllowExpandViewport = true;
17914
18308
  jQuery("#filteringByVisibility").html(on?'&#10004;':'');
17915
- listOnlyVisible = on;
17916
- if (on) listener = gDelegate.addListener('dragstart', onDragStart, true);
17917
- else if (listener) {
17918
- gDelegate.removeListener(listener);
17919
- listener = null;
18309
+ gListOnlyVisible = on;
18310
+ if (on) gDragStartListener = gDelegate.addListener('dragstart', onDragStart, true);
18311
+ else if (gDragStartListener) {
18312
+ gDelegate.removeListener(gDragStartListener);
18313
+ gDragStartListener = null;
17920
18314
  }
17921
18315
  return !on;
17922
18316
  }
17923
18317
  function toggleVisible() {
17924
- filterVisible(!listOnlyVisible);
18318
+ filterVisible(!gListOnlyVisible);
17925
18319
  }
17926
18320
  function filterBounds(bounds) {
17927
- var ret = gAllMeetings.filter((meeting) =>
18321
+ const ret = gAllMeetings.filter((meeting) =>
17928
18322
  gDelegate.contains(bounds, meeting.latitude, meeting.longitude));
17929
18323
  return ret;
17930
18324
  }
@@ -17934,31 +18328,31 @@ function MeetingMap(inConfig) {
17934
18328
  if ((gDelegate.getZoom()>=14) && gDelegate.contains(gDelegate.getBounds(), meeting.latitude, meeting.longitude)) {
17935
18329
  gDelegate.openMarker(meetingId);
17936
18330
  } else {
17937
- gDelegate.setViewToPosition({latitude: meeting.latitude, longitude: meeting.longitude}, filterMeetingsAndBounds, function() {gDelegate.openMarker(meetingId);});
18331
+ gDelegate.flyToFixedZoom({lat: meeting.latitude, lng: meeting.longitude}, config.focusedMeetingPopupZoomLevel ?? 14, function() {gDelegate.openMarker(meetingId);});
17938
18332
  }
17939
18333
  }
17940
18334
  function filterMeetingsAndBounds(bounds) {
17941
18335
  return filterMeetings(filterBounds(bounds));
17942
18336
  }
17943
18337
  function filterMeetings(in_meetings_array) {
17944
- var ret = in_meetings_array.filter(m => m.venue_type != 2);
18338
+ const ret = in_meetings_array.filter(m => m.venue_type != 2);
17945
18339
  if (gMeetingIdsFromCrouton != null) {
17946
18340
  return ret.filter((m) => gMeetingIdsFromCrouton.includes(m.id_bigint));
17947
18341
  }
17948
18342
  return ret;
17949
18343
  }
17950
- var _isPseudoFullscreen = false;
18344
+ var gIsPseudoFullscreen = false;
17951
18345
  function isFullscreen() {
17952
- var fullscreenElement =
18346
+ const fullscreenElement =
17953
18347
  document.fullscreenElement ||
17954
18348
  document.mozFullScreenElement ||
17955
18349
  document.webkitFullscreenElement ||
17956
18350
  document.msFullscreenElement;
17957
18351
 
17958
- return (fullscreenElement === gInDiv) || _isPseudoFullscreen;
18352
+ return (fullscreenElement === gInDiv) || gIsPseudoFullscreen;
17959
18353
  }
17960
18354
  function toggleFullscreen(options) {
17961
- var container = gInDiv;
18355
+ const container = gInDiv;
17962
18356
  if (isFullscreen()) {
17963
18357
  if (options && options.pseudoFullscreen) {
17964
18358
  _setFullscreen(false);
@@ -17989,10 +18383,9 @@ function MeetingMap(inConfig) {
17989
18383
  }
17990
18384
  }
17991
18385
  }
17992
- var _isPseudoFullscreen = false;
17993
18386
  function _setFullscreen(fullscreen) {
17994
- _isPseudoFullscreen = fullscreen;
17995
- var container = gInDiv;
18387
+ gIsPseudoFullscreen = fullscreen;
18388
+ const container = gInDiv;
17996
18389
  if (fullscreen) {
17997
18390
  L.DomUtil.addClass(container, 'leaflet-pseudo-fullscreen');
17998
18391
  } else {
@@ -18007,6 +18400,12 @@ function MeetingMap(inConfig) {
18007
18400
  }
18008
18401
  gDelegate.invalidateSize();
18009
18402
  if (!gAllMeetings) return;
18403
+ if (gLocationSearchResult) {
18404
+ searchResponseCallback();
18405
+ filterVisible(false);
18406
+ gDelegate.flyToFixedZoom(gLocationSearchResult.center, gLocationSearchResult.zoom, filterVisible);
18407
+ gLocationSearchResult = null;
18408
+ }
18010
18409
  if (fitBounds) gDelegate.fitBounds(
18011
18410
  ((gMeetingIdsFromCrouton) ? gAllMeetings.filter((m) => gMeetingIdsFromCrouton.includes(m.id_bigint)) : gAllMeetings)
18012
18411
  .reduce(function(a,m) {a.push([m.latitude, m.longitude]); return a;},[])
@@ -18017,14 +18416,14 @@ function MeetingMap(inConfig) {
18017
18416
  }
18018
18417
 
18019
18418
  function getDistance(p1, p2) {
18020
- var R = 6378137; // Earth’s mean radius in meter
18021
- var dLat = rad(p2.lat - p1.lat);
18022
- var dLong = rad(p2.lng - p1.lng);
18023
- var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
18419
+ const R = 6378137; // Earth’s mean radius in meter
18420
+ const dLat = rad(p2.lat - p1.lat);
18421
+ const dLong = rad(p2.lng - p1.lng);
18422
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
18024
18423
  Math.cos(rad(p1.lat)) * Math.cos(rad(p2.lat)) *
18025
18424
  Math.sin(dLong / 2) * Math.sin(dLong / 2);
18026
- var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
18027
- var d = R * c;
18425
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
18426
+ const d = R * c;
18028
18427
  return d; // returns the distance in meter
18029
18428
  }
18030
18429
  function getDistanceFromSearch(p) {
@@ -18047,7 +18446,7 @@ function MeetingMap(inConfig) {
18047
18446
  ****************************************************************************************/
18048
18447
  this.initialize = loadFromCrouton;
18049
18448
  this.showMap = showMap;
18050
- this.fillMap = filterFromCrouton;
18449
+ this.setFilteredIds = setFilteredIds;
18051
18450
  this.rowClick = focusOnMeeting;
18052
18451
  this.apiLoadedCallback = apiLoadedCallback;
18053
18452
  this.refreshMeetings = loadAllMeetings;
@@ -18057,17 +18456,22 @@ function MeetingMap(inConfig) {
18057
18456
  this.loadPopupMap = loadPopupMap;
18058
18457
  this.filterVisible = filterVisible;
18059
18458
  this.hasMapSearch = hasMapSearch;
18459
+ this.createLocationSearchButton = createLocationSearchButton;
18460
+ this.latLngToWebMercator = latLngToWebMercator;
18461
+ this.webMercatorToLatLng = webMercatorToLatLng;
18060
18462
  };
18061
18463
  MeetingMap.prototype.initialize = null;
18062
18464
  MeetingMap.prototype.showMap = null;
18063
- MeetingMap.prototype.fillMap = null;
18465
+ MeetingMap.prototype.setFilteredIds = null;
18064
18466
  MeetingMap.prototype.rowClick = null;
18065
18467
  MeetingMap.prototype.apiLoadedCallback = null;
18066
18468
  MeetingMap.prototype.refreshMeetings = null;
18067
18469
  MeetingMap.prototype.getDistanceFromSearch = null;
18068
-
18470
+ MeetingMap.prototype.latLngToWebMercator = null; // called from delegates - yuck!
18471
+ MeetingMap.prototype.webMercatorToLatLng = null; // called from delegates - yuck!
18069
18472
  MeetingMap.prototype.openModalWindow = null;
18070
18473
  MeetingMap.prototype.closeModalWindow = null;
18071
18474
  MeetingMap.prototype.loadPopupMap = null;
18072
18475
  MeetingMap.prototype.filterVisible = null;
18073
18476
  MeetingMap.prototype.hasMapSearch = null;
18477
+ MeetingMap.prototype.createLocationSearchButton = null;