gtfs-to-html 2.7.2 → 2.8.0

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.
Files changed (84) hide show
  1. package/package.json +21 -8
  2. package/.eslintrc.json +0 -28
  3. package/.husky/pre-commit +0 -4
  4. package/CHANGELOG.md +0 -1018
  5. package/app/index.js +0 -138
  6. package/bin/gtfs-to-html.js +0 -48
  7. package/config-sample.json +0 -59
  8. package/docker/Dockerfile +0 -14
  9. package/docker/README.md +0 -5
  10. package/docker/docker-compose.yml +0 -10
  11. package/examples/stop_attributes.txt +0 -6
  12. package/examples/timetable_notes.txt +0 -8
  13. package/examples/timetable_notes_references.txt +0 -8
  14. package/examples/timetable_pages.txt +0 -3
  15. package/examples/timetable_stop_order.txt +0 -16
  16. package/examples/timetables.txt +0 -9
  17. package/index.js +0 -1
  18. package/lib/file-utils.js +0 -202
  19. package/lib/formatters.js +0 -518
  20. package/lib/geojson-utils.js +0 -96
  21. package/lib/gtfs-to-html.js +0 -214
  22. package/lib/log-utils.js +0 -215
  23. package/lib/template-functions.js +0 -192
  24. package/lib/time-utils.js +0 -90
  25. package/lib/utils.js +0 -1702
  26. package/views/default/css/overview_styles.css +0 -197
  27. package/views/default/css/timetable_pdf_styles.css +0 -7
  28. package/views/default/css/timetable_styles.css +0 -447
  29. package/views/default/formatting_functions.pug +0 -113
  30. package/views/default/js/system-map.js +0 -594
  31. package/views/default/js/timetable-map.js +0 -358
  32. package/views/default/js/timetable-menu.js +0 -63
  33. package/views/default/layout.pug +0 -11
  34. package/views/default/overview.pug +0 -27
  35. package/views/default/overview_full.pug +0 -16
  36. package/views/default/timetable_continuation_as.pug +0 -7
  37. package/views/default/timetable_continuation_from.pug +0 -7
  38. package/views/default/timetable_horizontal.pug +0 -42
  39. package/views/default/timetable_hourly.pug +0 -30
  40. package/views/default/timetable_menu.pug +0 -48
  41. package/views/default/timetable_note_symbol.pug +0 -5
  42. package/views/default/timetable_stop_name.pug +0 -13
  43. package/views/default/timetable_stoptime.pug +0 -17
  44. package/views/default/timetable_vertical.pug +0 -67
  45. package/views/default/timetablepage.pug +0 -66
  46. package/views/default/timetablepage_full.pug +0 -22
  47. package/www/README.md +0 -33
  48. package/www/babel.config.js +0 -3
  49. package/www/blog/2020-07-07-New-Documentation.md +0 -12
  50. package/www/blog/2020-08-20-Version-1.0.0.md +0 -29
  51. package/www/blog/2021-11-06-CSV-Export.md +0 -26
  52. package/www/docs/additional-files.md +0 -24
  53. package/www/docs/configuration.md +0 -568
  54. package/www/docs/current-usage.md +0 -48
  55. package/www/docs/custom-templates.md +0 -13
  56. package/www/docs/introduction.md +0 -39
  57. package/www/docs/logging-sql-queries.md +0 -12
  58. package/www/docs/previewing-html-output.md +0 -24
  59. package/www/docs/processing-large-gtfs.md +0 -10
  60. package/www/docs/quick-start.md +0 -136
  61. package/www/docs/related-libraries.md +0 -54
  62. package/www/docs/reviewing-changes.md +0 -29
  63. package/www/docs/stop-attributes.md +0 -30
  64. package/www/docs/support.md +0 -12
  65. package/www/docs/timetable-notes-references.md +0 -44
  66. package/www/docs/timetable-notes.md +0 -33
  67. package/www/docs/timetable-pages.md +0 -37
  68. package/www/docs/timetable-stop-order.md +0 -63
  69. package/www/docs/timetables.md +0 -64
  70. package/www/docusaurus.config.js +0 -104
  71. package/www/package.json +0 -21
  72. package/www/sidebars.js +0 -10
  73. package/www/src/css/custom.css +0 -25
  74. package/www/src/pages/index.js +0 -270
  75. package/www/src/pages/styles.module.css +0 -53
  76. package/www/static/.nojekyll +0 -0
  77. package/www/static/img/favicon.ico +0 -0
  78. package/www/static/img/gtfs-to-html-logo.svg +0 -18
  79. package/www/static/img/overview-example.jpg +0 -0
  80. package/www/static/img/timetable-example.jpg +0 -0
  81. package/www/static/img/undraw_happy_music.svg +0 -1
  82. package/www/static/img/undraw_proud_coder.svg +0 -1
  83. package/www/static/img/undraw_spreadsheets.svg +0 -1
  84. package/www/yarn.lock +0 -8351
@@ -1,113 +0,0 @@
1
- -
2
- function getTimetableSummary(timetable) {
3
- let summary = `This table shows schedules for a selection of key stops on the route for ${timetable.timetable_label} ${timetable.dayList}.`;
4
- if (timetable.orientation === 'vertical') {
5
- summary += ' Stops and their schedule times are listed in the columns.';
6
- } else if (timetable.orientation === 'horizontal') {
7
- summary += ' Schedule times are listed in rows, starting with the stop name in the first cell of the row.';
8
- } else if (timetable.orientation === 'hourly') {
9
- summary += ' Schedule times are listed in rows, starting with the stop name in the first cell of the row and the minutes after the hour in the second row.';
10
- }
11
- return summary;
12
- }
13
-
14
- function isNullOrEmpty(value) {
15
- return value === null || value === '';
16
- }
17
-
18
- function formatFrequencyWarning(frequencies) {
19
- let warning = 'Trip times shown below are an example only. ';
20
- frequencies.forEach((frequency, idx) => {
21
- if (idx === 0) {
22
- warning += 'This route runs every ';
23
- } else {
24
- warning += ' and ';
25
- }
26
- warning += `${frequency.headway_min} minutes between ${frequency.start_formatted_time} and ${frequency.end_formatted_time}`;
27
- });
28
- warning += '.';
29
- return warning;
30
- }
31
-
32
- function formatAgencyName(agency) {
33
- if (!agency || !agency.agency_name) {
34
- return '';
35
- }
36
-
37
- return agency.agency_name;
38
- }
39
-
40
- function getAgencyTimetableGroups(timetablePages, agencies) {
41
- const agencyIds = [];
42
- for (const timetablePage of timetablePages) {
43
- agencyIds.push(...timetablePage.agency_ids);
44
- }
45
-
46
- const uniqueAgencyIds = _.uniq(_.compact(agencyIds));
47
-
48
- if (uniqueAgencyIds.length === 0) {
49
- return [{
50
- agency: _.first(agencies),
51
- timetablePages
52
- }];
53
- }
54
-
55
- return _.orderBy(uniqueAgencyIds.map(agencyId => {
56
- return {
57
- agency: agencies.find(agency => agency.agency_id === agencyId) || _.first(agencies),
58
- timetablePages: timetablePages.filter(timetablePage => timetablePage.agency_ids.includes(agencyId))
59
- };
60
- }), timetableGroup => timetableGroup.agency.agency_name.toLowerCase());
61
- }
62
-
63
- function prepareMapData(timetable) {
64
- const routes = {}
65
- const minifiedGeojson = {
66
- type: 'FeatureCollection',
67
- features: []
68
- }
69
-
70
- for (const feature of timetable.geojson.features) {
71
- if (feature.geometry.type.toLowerCase() === 'point') {
72
- for (const route of feature.properties.routes) {
73
- routes[route.route_id] = route
74
- }
75
-
76
- feature.properties.routes = feature.properties.routes.map(route => route.route_id)
77
-
78
- minifiedGeojson.features.push(_.omit(feature, ['location_type', 'tts_stop_name']))
79
- } else if (feature.geometry.type.toLowerCase() === 'linestring') {
80
- feature.properties = {
81
- route_color: feature.properties.route_color
82
- }
83
- minifiedGeojson.features.push(feature)
84
- } else if (feature.geometry.type.toLowerCase() === 'multilinestring') {
85
- feature.properties = {
86
- route_color: feature.properties.route_color
87
- }
88
- minifiedGeojson.features.push(feature)
89
- }
90
- }
91
-
92
- return {
93
- id: `timetable_id_${formatHtmlId(timetable.timetable_id)}`,
94
- routes,
95
- geojson: minifiedGeojson
96
- }
97
- }
98
-
99
- function getRouteColorsAsCss (route) {
100
- if (route && route.route_color) {
101
- return `background: #${route.route_color}; color: #${route.route_text_color ?? 'ffffff'};`
102
- }
103
-
104
- return ''
105
- }
106
-
107
- function formatRouteName(route) {
108
- if (isNullOrEmpty(route.route_long_name)) {
109
- return `Route ${route.route_short_name}`;
110
- }
111
-
112
- return route.route_long_name;
113
- }
@@ -1,594 +0,0 @@
1
- /* global window, document, _, $, mapboxgl */
2
- /* eslint prefer-arrow-callback: "off", no-unused-vars: "off" */
3
-
4
- const maps = {};
5
-
6
- function formatRouteColor(route) {
7
- return route.route_color || '#000000';
8
- }
9
-
10
- function formatRouteTextColor(route) {
11
- return route.route_text_color || '#FFFFFF';
12
- }
13
-
14
- function formatRoute(route) {
15
- const html = route.route_url
16
- ? $('<a>').attr('href', route.route_url)
17
- : $('<div>');
18
-
19
- html.addClass('map-route-item');
20
-
21
- // Only add color swatch if route has a color
22
- const routeItemDivs = [];
23
-
24
- if (route.route_color) {
25
- routeItemDivs.push(
26
- $('<div>')
27
- .addClass('route-color-swatch')
28
- .css('backgroundColor', formatRouteColor(route))
29
- .css('color', formatRouteTextColor(route))
30
- .text(route.route_short_name ?? ''),
31
- );
32
- }
33
- routeItemDivs.push(
34
- $('<div>')
35
- .addClass('underline-hover')
36
- .text(route.route_long_name ?? `Route ${route.route_short_name}`),
37
- );
38
-
39
- html.append(routeItemDivs);
40
-
41
- return html.prop('outerHTML');
42
- }
43
-
44
- function formatRoutePopup(features) {
45
- const html = $('<div>');
46
-
47
- if (features.length > 1) {
48
- $('<div>').addClass('popup-title').text('Routes').appendTo(html);
49
- }
50
-
51
- $(html).append(features.map((feature) => formatRoute(feature.properties)));
52
-
53
- return html.prop('outerHTML');
54
- }
55
-
56
- function formatStopPopup(feature) {
57
- const routes = JSON.parse(feature.properties.routes);
58
- const html = $('<div>');
59
-
60
- $('<div>')
61
- .addClass('popup-title')
62
- .text(feature.properties.stop_name)
63
- .appendTo(html);
64
-
65
- if (feature.properties.stop_code ?? false) {
66
- $('<div>')
67
- .html([
68
- $('<label>').addClass('popup-label').text('Stop Code:'),
69
- $('<strong>').text(feature.properties.stop_code),
70
- ])
71
- .appendTo(html);
72
- }
73
-
74
- $('<label>').text('Routes Served:').appendTo(html);
75
-
76
- $(html).append(
77
- $('<div>')
78
- .addClass('route-list')
79
- .html(routes.map((route) => formatRoute(route))),
80
- );
81
-
82
- $('<a>')
83
- .addClass('btn-blue btn-sm')
84
- .prop(
85
- 'href',
86
- `https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&heading=0&pitch=0&fov=90`,
87
- )
88
- .prop('target', '_blank')
89
- .prop('rel', 'noopener noreferrer')
90
- .html('View on Streetview')
91
- .appendTo(html);
92
-
93
- return html.prop('outerHTML');
94
- }
95
-
96
- function getBounds(geojson) {
97
- const bounds = new mapboxgl.LngLatBounds();
98
- for (const feature of geojson.features) {
99
- if (feature.geometry.type.toLowerCase() === 'point') {
100
- bounds.extend(feature.geometry.coordinates);
101
- } else if (feature.geometry.type.toLowerCase() === 'linestring') {
102
- for (const coordinate of feature.geometry.coordinates) {
103
- bounds.extend(coordinate);
104
- }
105
- } else if (feature.geometry.type.toLowerCase() === 'multilinestring') {
106
- for (const linestring of feature.geometry.coordinates) {
107
- for (const coordinate of linestring) {
108
- bounds.extend(coordinate);
109
- }
110
- }
111
- }
112
- }
113
-
114
- return bounds;
115
- }
116
-
117
- function createSystemMap(id, geojson) {
118
- const defaultRouteColor = '#000000';
119
- const lineLayout = {
120
- 'line-join': 'round',
121
- 'line-cap': 'round',
122
- };
123
-
124
- if (!geojson || geojson.features.length === 0) {
125
- $('#' + id).hide();
126
- return false;
127
- }
128
-
129
- const bounds = getBounds(geojson);
130
- const map = new mapboxgl.Map({
131
- container: id,
132
- style: 'mapbox://styles/mapbox/light-v10',
133
- center: bounds.getCenter(),
134
- zoom: 12,
135
- });
136
- const routes = {};
137
-
138
- for (const feature of geojson.features) {
139
- routes[feature.properties.route_id] = feature.properties;
140
- }
141
-
142
- map.scrollZoom.disable();
143
- map.addControl(new mapboxgl.NavigationControl());
144
-
145
- map.on('load', () => {
146
- map.fitBounds(bounds, {
147
- padding: 20,
148
- duration: 0,
149
- });
150
-
151
- // Turn off Points of Interest labels
152
- map.setLayoutProperty('poi-label', 'visibility', 'none');
153
-
154
- // Find the index of the first symbol layer in the map style to put the route lines underneath
155
- let firstSymbolId;
156
- for (const layer of map.getStyle().layers) {
157
- if (layer.type === 'symbol') {
158
- firstSymbolId = layer.id;
159
- break;
160
- }
161
- }
162
-
163
- // Add route drop shadow outline first
164
- map.addLayer(
165
- {
166
- id: 'route-line-shadows',
167
- type: 'line',
168
- source: {
169
- type: 'geojson',
170
- data: geojson,
171
- },
172
- paint: {
173
- 'line-color': '#000000',
174
- 'line-opacity': 0.3,
175
- 'line-width': {
176
- base: 12,
177
- stops: [
178
- [14, 20],
179
- [18, 42],
180
- ],
181
- },
182
- 'line-blur': {
183
- base: 12,
184
- stops: [
185
- [14, 20],
186
- [18, 42],
187
- ],
188
- },
189
- },
190
- layout: lineLayout,
191
- filter: ['!has', 'stop_id'],
192
- },
193
- firstSymbolId,
194
- );
195
-
196
- // Add highlighted route drop shadow outlines next
197
- map.addLayer(
198
- {
199
- id: 'highlighted-route-line-shadows',
200
- type: 'line',
201
- source: {
202
- type: 'geojson',
203
- data: geojson,
204
- },
205
- paint: {
206
- 'line-color': '#000000',
207
- 'line-opacity': 0.3,
208
- 'line-width': {
209
- base: 16,
210
- stops: [
211
- [14, 24],
212
- [18, 50],
213
- ],
214
- },
215
- 'line-blur': {
216
- base: 16,
217
- stops: [
218
- [14, 24],
219
- [18, 50],
220
- ],
221
- },
222
- },
223
- layout: lineLayout,
224
- filter: ['==', ['get', 'route_id'], 'none'],
225
- },
226
- firstSymbolId,
227
- );
228
-
229
- // Add white outlines to routes next
230
- map.addLayer(
231
- {
232
- id: `route-outlines`,
233
- type: 'line',
234
- source: {
235
- type: 'geojson',
236
- data: geojson,
237
- },
238
- paint: {
239
- 'line-color': '#FFFFFF',
240
- 'line-opacity': 1,
241
- 'line-width': {
242
- base: 8,
243
- stops: [
244
- [14, 12],
245
- [18, 32],
246
- ],
247
- },
248
- },
249
- layout: lineLayout,
250
- filter: ['has', 'route_id'],
251
- },
252
- firstSymbolId,
253
- );
254
-
255
- // Add route lines next
256
- map.addLayer(
257
- {
258
- id: 'routes',
259
- type: 'line',
260
- source: {
261
- type: 'geojson',
262
- data: geojson,
263
- },
264
- paint: {
265
- 'line-color': ['coalesce', ['get', 'route_color'], defaultRouteColor],
266
- 'line-opacity': 1,
267
- 'line-width': {
268
- base: 4,
269
- stops: [
270
- [14, 6],
271
- [18, 16],
272
- ],
273
- },
274
- },
275
- layout: lineLayout,
276
- filter: ['has', 'route_id'],
277
- },
278
- firstSymbolId,
279
- );
280
-
281
- // Add highlighted route white outlines next
282
- map.addLayer(
283
- {
284
- id: `highlighted-route-outlines`,
285
- type: 'line',
286
- source: {
287
- type: 'geojson',
288
- data: geojson,
289
- },
290
- paint: {
291
- 'line-color': '#FFFFFF',
292
- 'line-opacity': 1,
293
- 'line-width': {
294
- base: 10,
295
- stops: [
296
- [14, 16],
297
- [18, 40],
298
- ],
299
- },
300
- },
301
- layout: lineLayout,
302
- filter: ['==', ['get', 'route_id'], 'none'],
303
- },
304
- firstSymbolId,
305
- );
306
-
307
- // Add highlighted route lines next
308
- map.addLayer(
309
- {
310
- id: 'highlighted-routes',
311
- type: 'line',
312
- source: {
313
- type: 'geojson',
314
- data: geojson,
315
- },
316
- paint: {
317
- 'line-color': ['coalesce', ['get', 'route_color'], defaultRouteColor],
318
- 'line-opacity': 1,
319
- 'line-width': {
320
- base: 6,
321
- stops: [
322
- [14, 8],
323
- [18, 20],
324
- ],
325
- },
326
- },
327
- layout: lineLayout,
328
- filter: ['==', ['get', 'route_id'], 'none'],
329
- },
330
- firstSymbolId,
331
- );
332
-
333
- // Add stops when zoomed in
334
- map.addLayer({
335
- id: 'stops',
336
- type: 'circle',
337
- source: {
338
- type: 'geojson',
339
- data: geojson,
340
- },
341
- paint: {
342
- 'circle-color': '#fff',
343
- 'circle-radius': {
344
- base: 1.75,
345
- stops: [
346
- [12, 4],
347
- [22, 100],
348
- ],
349
- },
350
- 'circle-stroke-color': '#3F4A5C',
351
- 'circle-stroke-width': 2,
352
- 'circle-opacity': ['interpolate', ['linear'], ['zoom'], 13, 0, 13.5, 1],
353
- 'circle-stroke-opacity': [
354
- 'interpolate',
355
- ['linear'],
356
- ['zoom'],
357
- 13,
358
- 0,
359
- 13.5,
360
- 1,
361
- ],
362
- },
363
- filter: ['has', 'stop_id'],
364
- });
365
-
366
- // Layer for highlighted stops
367
- map.addLayer({
368
- id: 'stops-highlighted',
369
- type: 'circle',
370
- source: {
371
- type: 'geojson',
372
- data: geojson,
373
- },
374
- paint: {
375
- 'circle-color': '#fff',
376
- 'circle-radius': {
377
- base: 1.75,
378
- stops: [
379
- [12, 5],
380
- [22, 125],
381
- ],
382
- },
383
- 'circle-stroke-width': 2,
384
- 'circle-stroke-color': '#3f4a5c',
385
- 'circle-opacity': ['interpolate', ['linear'], ['zoom'], 13, 0, 13.5, 1],
386
- 'circle-stroke-opacity': [
387
- 'interpolate',
388
- ['linear'],
389
- ['zoom'],
390
- 13,
391
- 0,
392
- 13.5,
393
- 1,
394
- ],
395
- },
396
- filter: ['==', 'stop_id', ''],
397
- });
398
-
399
- // Add labels
400
- map.addLayer({
401
- id: 'route-labels',
402
- type: 'symbol',
403
- source: {
404
- type: 'geojson',
405
- data: geojson,
406
- },
407
- layout: {
408
- 'symbol-placement': 'line',
409
- 'text-field': ['get', 'route_short_name'],
410
- 'text-size': 14,
411
- },
412
- paint: {
413
- 'text-color': '#000000',
414
- 'text-halo-width': 2,
415
- 'text-halo-color': '#ffffff',
416
- },
417
- filter: ['has', 'route_short_name'],
418
- });
419
-
420
- map.on('mousemove', (event) => {
421
- const features = map.queryRenderedFeatures(event.point, {
422
- layers: ['routes', 'route-outlines', 'stops-highlighted', 'stops'],
423
- });
424
- if (features.length > 0) {
425
- map.getCanvas().style.cursor = 'pointer';
426
- highlightRoutes(
427
- _.compact(
428
- _.uniq(features.map((feature) => feature.properties.route_id)),
429
- ),
430
- );
431
-
432
- if (features.some((feature) => feature.layer.id === 'stops')) {
433
- highlightStop(
434
- features.find((feature) => feature.layer.id === 'stops').properties
435
- .stop_id,
436
- );
437
- }
438
- } else {
439
- map.getCanvas().style.cursor = '';
440
- unHighlightRoutes();
441
- unHighlightStop();
442
- }
443
- });
444
-
445
- map.on('click', (event) => {
446
- // Set bbox as 5px rectangle area around clicked point
447
- const bbox = [
448
- [event.point.x - 5, event.point.y - 5],
449
- [event.point.x + 5, event.point.y + 5],
450
- ];
451
-
452
- const stopFeatures = map.queryRenderedFeatures(bbox, {
453
- layers: ['stops-highlighted', 'stops'],
454
- });
455
-
456
- if (stopFeatures && stopFeatures.length > 0) {
457
- // Get the stop feature and show popup
458
- const stopFeature = stopFeatures[0];
459
-
460
- new mapboxgl.Popup()
461
- .setLngLat(stopFeature.geometry.coordinates)
462
- .setHTML(formatStopPopup(stopFeature))
463
- .addTo(map);
464
- } else {
465
- const routeFeatures = map.queryRenderedFeatures(bbox, {
466
- layers: ['routes', 'route-outlines'],
467
- });
468
-
469
- if (routeFeatures && routeFeatures.length > 0) {
470
- const routes = _.orderBy(
471
- _.uniqBy(
472
- routeFeatures,
473
- (feature) => feature.properties.route_short_name,
474
- ),
475
- (feature) =>
476
- Number.parseInt(feature.properties.route_short_name, 10),
477
- );
478
-
479
- new mapboxgl.Popup()
480
- .setLngLat(event.lngLat)
481
- .setHTML(formatRoutePopup(routes))
482
- .addTo(map);
483
- }
484
- }
485
- });
486
-
487
- function highlightStop(stopId) {
488
- map.setFilter('stops-highlighted', ['==', 'stop_id', stopId]);
489
- }
490
-
491
- function unHighlightStop() {
492
- map.setFilter('stops-highlighted', ['==', 'stop_id', '']);
493
- }
494
-
495
- function highlightRoutes(routeIds, zoom) {
496
- map.setFilter('highlighted-routes', [
497
- 'all',
498
- ['has', 'route_short_name'],
499
- ['in', ['get', 'route_id'], ['literal', routeIds]],
500
- ]);
501
- map.setFilter('highlighted-route-outlines', [
502
- 'all',
503
- ['has', 'route_short_name'],
504
- ['in', ['get', 'route_id'], ['literal', routeIds]],
505
- ]);
506
- map.setFilter('highlighted-route-line-shadows', [
507
- 'all',
508
- ['has', 'route_short_name'],
509
- ['in', ['get', 'route_id'], ['literal', routeIds]],
510
- ]);
511
-
512
- // Show labels only for highlighted route
513
- map.setFilter('route-labels', [
514
- 'in',
515
- ['get', 'route_id'],
516
- ['literal', routeIds],
517
- ]);
518
-
519
- const routeLineOpacity = 0.4;
520
-
521
- // De-emphasize other routes
522
- map.setPaintProperty('routes', 'line-opacity', routeLineOpacity);
523
- map.setPaintProperty('route-outlines', 'line-opacity', routeLineOpacity);
524
- map.setPaintProperty(
525
- 'route-line-shadows',
526
- 'line-opacity',
527
- routeLineOpacity,
528
- );
529
-
530
- const highlightedFeatures = geojson.features.filter((feature) =>
531
- routeIds.includes(feature.properties.route_id),
532
- );
533
-
534
- if (highlightedFeatures.length > 0 && zoom) {
535
- const zoomBounds = getBounds({
536
- features: highlightedFeatures,
537
- });
538
- map.fitBounds(zoomBounds, {
539
- padding: 20,
540
- });
541
- }
542
- }
543
-
544
- function unHighlightRoutes(zoom) {
545
- map.setFilter('highlighted-routes', ['==', ['get', 'route_id'], 'none']);
546
- map.setFilter('highlighted-route-outlines', [
547
- '==',
548
- ['get', 'route_id'],
549
- 'none',
550
- ]);
551
- map.setFilter('highlighted-route-line-shadows', [
552
- '==',
553
- ['get', 'route_id'],
554
- 'none',
555
- ]);
556
-
557
- // Show labels for all routes
558
- map.setFilter('route-labels', ['has', 'route_short_name']);
559
-
560
- const routeLineOpacity = 1;
561
-
562
- // Re-emphasize other routes
563
- map.setPaintProperty('routes', 'line-opacity', routeLineOpacity);
564
- map.setPaintProperty('route-outlines', 'line-opacity', routeLineOpacity);
565
- map.setPaintProperty(
566
- 'route-line-shadows',
567
- 'line-opacity',
568
- routeLineOpacity,
569
- );
570
-
571
- if (zoom) {
572
- map.fitBounds(bounds);
573
- }
574
- }
575
-
576
- // On table hover, highlight route on map
577
- $(() => {
578
- $('.overview-list a').hover((event) => {
579
- const routeIdString = $(event.target).data('route-ids');
580
- if (routeIdString) {
581
- const routeIds = routeIdString.toString().split(',');
582
- highlightRoutes(routeIds, true);
583
- }
584
- });
585
-
586
- $('.overview-list').hover(
587
- () => {},
588
- () => unHighlightRoutes(true),
589
- );
590
- });
591
- });
592
-
593
- maps[id] = map;
594
- }