mobility-toolbox-js 2.0.0-beta.8 → 2.0.1-beta.13

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 (304) hide show
  1. package/api/RoutingAPI.js +15 -0
  2. package/api/RoutingAPI.test.js +25 -0
  3. package/api/StopsAPI.js +12 -0
  4. package/api/StopsAPI.test.js +22 -0
  5. package/api/TralisAPI.js +359 -0
  6. package/api/TralisAPI.test.js +67 -0
  7. package/{src/api/tralis → api}/TralisAPIUtils.js +2 -32
  8. package/api/index.js +3 -0
  9. package/{index.html → api/typedefs.js} +0 -0
  10. package/common/Tracker.js +93 -0
  11. package/common/api/HttpAPI.js +30 -0
  12. package/common/api/HttpAPI.test.js +50 -0
  13. package/common/api/WebSocketAPI.js +175 -0
  14. package/{src/api/tralis/WebSocketConnector.test.js → common/api/WebSocketAPI.test.js} +100 -145
  15. package/common/controls/Control.js +81 -0
  16. package/{src/common → common}/controls/Control.test.js +32 -43
  17. package/common/index.js +4 -0
  18. package/common/layers/Layer.js +213 -0
  19. package/{src/common → common}/layers/Layer.test.js +185 -244
  20. package/common/mixins/CopyrightMixin.js +24 -0
  21. package/common/mixins/SearchMixin.js +110 -0
  22. package/common/mixins/TralisLayerMixin.js +479 -0
  23. package/common/styles/index.js +4 -0
  24. package/{src/common → common}/styles/trackerDefaultStyle.js +39 -175
  25. package/common/styles/trackerDelayStyle.js +8 -0
  26. package/{src/common → common}/styles/trackerSimpleStyle.js +4 -8
  27. package/{src/common → common}/trackerConfig.js +61 -99
  28. package/common/trackerConfig.test.js +23 -0
  29. package/{src/doc/examples/ol-mapbox-layer.md → common/typedefs.js} +0 -0
  30. package/common/utils/createTrackerFilters.js +56 -0
  31. package/common/utils/createTrackerFilters.test.js +79 -0
  32. package/{src/common → common}/utils/getMapboxMapCopyrights.js +3 -16
  33. package/common/utils/getMapboxMapCopyrights.test.js +40 -0
  34. package/{src/common → common}/utils/getMapboxStyleUrl.js +3 -13
  35. package/{src/common → common}/utils/getVehiclePosition.js +3 -33
  36. package/common/utils/index.js +5 -0
  37. package/common/utils/removeDuplicate.js +8 -0
  38. package/common/utils/removeDuplicate.test.js +19 -0
  39. package/{src/common → common}/utils/sortByDelay.js +2 -7
  40. package/common/utils/timeUtils.js +20 -0
  41. package/common/utils/timeUtils.test.js +10 -0
  42. package/index.js +8 -0
  43. package/mapbox/controls/CopyrightControl.js +29 -0
  44. package/mapbox/controls/index.js +1 -0
  45. package/mapbox/index.js +4 -0
  46. package/mapbox/layers/Layer.js +57 -0
  47. package/mapbox/layers/Layer.test.js +182 -0
  48. package/mapbox/layers/TralisLayer.js +182 -0
  49. package/{src/mapbox → mapbox}/layers/TralisLayer.test.js +12 -14
  50. package/mapbox/layers/index.js +2 -0
  51. package/{src/mapbox → mapbox}/utils.js +7 -21
  52. package/mbt.js +50444 -0
  53. package/mbt.js.map +7 -0
  54. package/mbt.min.js +1005 -0
  55. package/mbt.min.js.map +7 -0
  56. package/ol/controls/CopyrightControl.js +42 -0
  57. package/ol/controls/CopyrightControl.test.js +165 -0
  58. package/ol/controls/RoutingControl.js +387 -0
  59. package/ol/controls/RoutingControl.test.js +151 -0
  60. package/ol/controls/StopFinderControl.js +10 -0
  61. package/ol/controls/StopFinderControl.test.js +48 -0
  62. package/ol/controls/index.js +3 -0
  63. package/ol/index.js +5 -0
  64. package/ol/layers/Layer.js +88 -0
  65. package/ol/layers/Layer.test.js +174 -0
  66. package/ol/layers/MapboxLayer.js +203 -0
  67. package/{src/ol → ol}/layers/MapboxLayer.test.js +58 -84
  68. package/ol/layers/MapboxStyleLayer.js +187 -0
  69. package/{src/ol → ol}/layers/MapboxStyleLayer.test.js +97 -128
  70. package/ol/layers/MaplibreLayer.js +139 -0
  71. package/ol/layers/RoutingLayer.js +61 -0
  72. package/{src/ol → ol}/layers/RoutingLayer.test.js +15 -24
  73. package/ol/layers/TralisLayer.js +185 -0
  74. package/ol/layers/TralisLayer.test.js +79 -0
  75. package/ol/layers/VectorLayer.js +22 -0
  76. package/{src/ol → ol}/layers/VectorLayer.test.js +34 -45
  77. package/ol/layers/WMSLayer.js +38 -0
  78. package/ol/layers/WMSLayer.test.js +76 -0
  79. package/ol/layers/index.js +8 -0
  80. package/{src/ol → ol}/styles/fullTrajectoryDelayStyle.js +11 -15
  81. package/ol/styles/fullTrajectoryStyle.js +43 -0
  82. package/ol/styles/index.js +2 -0
  83. package/package.json +34 -74
  84. package/.babelrc +0 -6
  85. package/.esdoc.json +0 -17
  86. package/.eslintignore +0 -1
  87. package/.github/workflows/conventional-pr-title.yml +0 -21
  88. package/.github/workflows/cypress.yml +0 -29
  89. package/.github/workflows/nodejs.yml +0 -28
  90. package/.husky/commit-msg +0 -4
  91. package/.husky/post-checkout +0 -4
  92. package/.husky/post-merge +0 -4
  93. package/.husky/post-rebase +0 -4
  94. package/.husky/pre-commit +0 -4
  95. package/.neutrinorc.js +0 -176
  96. package/.nvmrc +0 -1
  97. package/CHANGELOG.md +0 -10
  98. package/LICENSE +0 -21
  99. package/__mocks__/mapbox-gl.js +0 -81
  100. package/__mocks__/maplibre-gl.js +0 -81
  101. package/commitlint.config.js +0 -1
  102. package/cypress/fixtures/example.json +0 -5
  103. package/cypress/integration/examples/api.spec.js +0 -7
  104. package/cypress/integration/examples/examples.spec.js +0 -7
  105. package/cypress/integration/examples/navigation.spec.js +0 -29
  106. package/cypress/plugins/index.js +0 -21
  107. package/cypress/support/commands.js +0 -25
  108. package/cypress/support/index.js +0 -20
  109. package/cypress.json +0 -4
  110. package/data/fetchRoute.json +0 -292
  111. package/data/fetchTrajectories.json +0 -18
  112. package/data/fetchTrajectoryById.json +0 -3
  113. package/data/fetchTrajectoryStations.json +0 -18
  114. package/data/stopsSearch.json +0 -15
  115. package/documentation.yml +0 -4
  116. package/esdoc/README.md +0 -27
  117. package/esdoc/plugins/MyPlugin.js +0 -69
  118. package/esdoc/plugins/dynamic-property-plugin/Plugin.js +0 -50
  119. package/esdoc/plugins/externals-plugin/Plugin.js +0 -45
  120. package/esdoc/plugins/externals-plugin/externals.js +0 -96
  121. package/global-setup.js +0 -3
  122. package/indexweb.html +0 -49
  123. package/jest.config.js +0 -5
  124. package/pull_request_template.md +0 -17
  125. package/renovate.json +0 -4
  126. package/scripts/read-pkg-json.js +0 -22
  127. package/src/api/index.js +0 -3
  128. package/src/api/routing/RoutingAPI.js +0 -44
  129. package/src/api/routing/RoutingAPI.test.js +0 -41
  130. package/src/api/stops/StopsAPI.js +0 -41
  131. package/src/api/stops/StopsAPI.test.js +0 -34
  132. package/src/api/tralis/TralisAPI.js +0 -731
  133. package/src/api/tralis/TralisAPI.test.js +0 -75
  134. package/src/api/tralis/WebSocketConnector.js +0 -338
  135. package/src/api/tralis/typedefs.js +0 -81
  136. package/src/assets/Lato-Black.ttf +0 -0
  137. package/src/assets/Lato-BlackItalic.ttf +0 -0
  138. package/src/assets/Lato-Bold.ttf +0 -0
  139. package/src/assets/Lato-BoldItalic.ttf +0 -0
  140. package/src/assets/Lato-Italic.ttf +0 -0
  141. package/src/assets/Lato-Light.ttf +0 -0
  142. package/src/assets/Lato-LightItalic.ttf +0 -0
  143. package/src/assets/Lato-Regular.ttf +0 -0
  144. package/src/assets/Lato-Thin.ttf +0 -0
  145. package/src/assets/Lato-ThinItalic.ttf +0 -0
  146. package/src/assets/OFL.txt +0 -93
  147. package/src/common/Tracker.js +0 -197
  148. package/src/common/api/api.js +0 -64
  149. package/src/common/api/api.test.js +0 -68
  150. package/src/common/controls/Control.js +0 -146
  151. package/src/common/index.js +0 -5
  152. package/src/common/layers/Layer.js +0 -404
  153. package/src/common/mixins/CopyrightMixin.js +0 -48
  154. package/src/common/mixins/SearchMixin.js +0 -176
  155. package/src/common/mixins/TralisLayerMixin.js +0 -930
  156. package/src/common/styles/index.js +0 -4
  157. package/src/common/styles/trackerDelayStyle.js +0 -17
  158. package/src/common/trackerConfig.test.js +0 -25
  159. package/src/common/typedefs.js +0 -23
  160. package/src/common/utils/createTrackerFilters.js +0 -87
  161. package/src/common/utils/createTrackerFilters.test.js +0 -95
  162. package/src/common/utils/getMapboxMapCopyrights.test.js +0 -47
  163. package/src/common/utils/index.js +0 -5
  164. package/src/common/utils/removeDuplicate.js +0 -22
  165. package/src/common/utils/removeDuplicate.test.js +0 -22
  166. package/src/common/utils/timeUtils.js +0 -44
  167. package/src/common/utils/timeUtils.test.js +0 -16
  168. package/src/doc/App.js +0 -116
  169. package/src/doc/App.scss +0 -51
  170. package/src/doc/_redirects +0 -2
  171. package/src/doc/components/CodeSandboxButton.js +0 -103
  172. package/src/doc/components/Documentation.js +0 -40
  173. package/src/doc/components/Esdoc/Anchor.js +0 -57
  174. package/src/doc/components/Esdoc/ClassDoc.js +0 -272
  175. package/src/doc/components/Esdoc/DeprecatedHTML.js +0 -16
  176. package/src/doc/components/Esdoc/DetailDocs.js +0 -281
  177. package/src/doc/components/Esdoc/DetailHTML.js +0 -33
  178. package/src/doc/components/Esdoc/DirectSubclassHTML.js +0 -30
  179. package/src/doc/components/Esdoc/DocBuilderUtils.js +0 -694
  180. package/src/doc/components/Esdoc/DocLinkHTML.js +0 -62
  181. package/src/doc/components/Esdoc/DocsLinkHTML.js +0 -38
  182. package/src/doc/components/Esdoc/Esdoc.js +0 -63
  183. package/src/doc/components/Esdoc/EsdocContent.js +0 -51
  184. package/src/doc/components/Esdoc/EsdocNavigation.js +0 -13
  185. package/src/doc/components/Esdoc/EsdocSearch.js +0 -81
  186. package/src/doc/components/Esdoc/ExperimentalHTML.js +0 -17
  187. package/src/doc/components/Esdoc/ExtendsChainHTML.js +0 -32
  188. package/src/doc/components/Esdoc/FileDocLinkHTML.js +0 -60
  189. package/src/doc/components/Esdoc/IdentifiersDoc.js +0 -113
  190. package/src/doc/components/Esdoc/IndirectSubclassHTML.js +0 -30
  191. package/src/doc/components/Esdoc/InheritedSummaryDoc.js +0 -70
  192. package/src/doc/components/Esdoc/InheritedSummaryHTML.js +0 -38
  193. package/src/doc/components/Esdoc/MixinClassesHTML.js +0 -29
  194. package/src/doc/components/Esdoc/NavDoc.js +0 -112
  195. package/src/doc/components/Esdoc/OverrideMethod.js +0 -44
  196. package/src/doc/components/Esdoc/OverrideMethodDescription.js +0 -35
  197. package/src/doc/components/Esdoc/Properties.js +0 -89
  198. package/src/doc/components/Esdoc/README.md +0 -45
  199. package/src/doc/components/Esdoc/SignatureHTML.js +0 -123
  200. package/src/doc/components/Esdoc/SingleDoc.js +0 -31
  201. package/src/doc/components/Esdoc/SummaryDoc.js +0 -160
  202. package/src/doc/components/Esdoc/SummaryHTML.js +0 -96
  203. package/src/doc/components/Esdoc/TypeDocLinkHTML.js +0 -249
  204. package/src/doc/components/Esdoc/css/identifiers.css +0 -38
  205. package/src/doc/components/Esdoc/css/search.css +0 -76
  206. package/src/doc/components/Esdoc/css/style.css +0 -603
  207. package/src/doc/components/Esdoc/index.js +0 -7
  208. package/src/doc/components/Example.js +0 -153
  209. package/src/doc/components/Examples.js +0 -183
  210. package/src/doc/components/Home.js +0 -106
  211. package/src/doc/components/TrackerExample.js +0 -38
  212. package/src/doc/examples/assets/tralis-live-map/index.js +0 -11
  213. package/src/doc/examples/assets/tralis-live-map/s1kreis.svg +0 -105
  214. package/src/doc/examples/assets/tralis-live-map/s20kreis.svg +0 -101
  215. package/src/doc/examples/assets/tralis-live-map/s2kreis.svg +0 -95
  216. package/src/doc/examples/assets/tralis-live-map/s3kreis.svg +0 -95
  217. package/src/doc/examples/assets/tralis-live-map/s4kreis.svg +0 -95
  218. package/src/doc/examples/assets/tralis-live-map/s6kreis.svg +0 -95
  219. package/src/doc/examples/assets/tralis-live-map/s7kreis.svg +0 -95
  220. package/src/doc/examples/assets/tralis-live-map/s8kreis.svg +0 -93
  221. package/src/doc/examples/assets/tralis-live-map/unknown.svg +0 -107
  222. package/src/doc/examples/mb-copyright.html +0 -26
  223. package/src/doc/examples/mb-copyright.js +0 -37
  224. package/src/doc/examples/mb-tracker.html +0 -1
  225. package/src/doc/examples/mb-tracker.js +0 -39
  226. package/src/doc/examples/mb-tracker.md +0 -1
  227. package/src/doc/examples/mb-tralis.html +0 -1
  228. package/src/doc/examples/mb-tralis.js +0 -34
  229. package/src/doc/examples/ol-copyright.html +0 -26
  230. package/src/doc/examples/ol-copyright.js +0 -43
  231. package/src/doc/examples/ol-mapbox-layer.html +0 -1
  232. package/src/doc/examples/ol-mapbox-layer.js +0 -28
  233. package/src/doc/examples/ol-mapbox-style-layer.html +0 -12
  234. package/src/doc/examples/ol-mapbox-style-layer.js +0 -44
  235. package/src/doc/examples/ol-query.html +0 -32
  236. package/src/doc/examples/ol-query.js +0 -83
  237. package/src/doc/examples/ol-routing.html +0 -26
  238. package/src/doc/examples/ol-routing.js +0 -59
  239. package/src/doc/examples/ol-routing.md +0 -1
  240. package/src/doc/examples/ol-stop-finder.html +0 -15
  241. package/src/doc/examples/ol-stop-finder.js +0 -31
  242. package/src/doc/examples/ol-stop-finder.md +0 -1
  243. package/src/doc/examples/ol-tracker.html +0 -1
  244. package/src/doc/examples/ol-tracker.js +0 -44
  245. package/src/doc/examples/ol-tracker.md +0 -1
  246. package/src/doc/examples/ol-tralis.html +0 -5
  247. package/src/doc/examples/ol-tralis.js +0 -57
  248. package/src/doc/examples/tralis-live-map.html +0 -1
  249. package/src/doc/examples/tralis-live-map.js +0 -51
  250. package/src/doc/examples/tralis-live-map.md +0 -3
  251. package/src/doc/examples.js +0 -107
  252. package/src/doc/img/examples/live_tracker_mb.jpg +0 -0
  253. package/src/doc/img/examples/live_tracker_munich.jpg +0 -0
  254. package/src/doc/img/examples/live_tracker_ol.jpg +0 -0
  255. package/src/doc/img/examples/mapbox.jpg +0 -0
  256. package/src/doc/img/examples/mapbox_style.jpg +0 -0
  257. package/src/doc/img/examples/ol-copyright.png +0 -0
  258. package/src/doc/img/examples/query_objects.jpg +0 -0
  259. package/src/doc/img/examples/routing.jpg +0 -0
  260. package/src/doc/img/examples/simple_map.jpg +0 -0
  261. package/src/doc/img/examples/stops.jpg +0 -0
  262. package/src/doc/img/favico.ico +0 -0
  263. package/src/doc/index.js +0 -21
  264. package/src/iife.js +0 -7
  265. package/src/index.js +0 -10
  266. package/src/mapbox/controls/CopyrightControl.js +0 -58
  267. package/src/mapbox/controls/index.js +0 -2
  268. package/src/mapbox/index.js +0 -4
  269. package/src/mapbox/layers/Layer.js +0 -118
  270. package/src/mapbox/layers/Layer.test.js +0 -202
  271. package/src/mapbox/layers/TralisLayer.js +0 -329
  272. package/src/mapbox/layers/index.js +0 -2
  273. package/src/ol/README.md +0 -0
  274. package/src/ol/controls/CopyrightControl.js +0 -80
  275. package/src/ol/controls/CopyrightControl.test.js +0 -211
  276. package/src/ol/controls/RoutingControl.js +0 -752
  277. package/src/ol/controls/RoutingControl.test.js +0 -216
  278. package/src/ol/controls/StopFinderControl.js +0 -38
  279. package/src/ol/controls/StopFinderControl.test.js +0 -59
  280. package/src/ol/controls/index.js +0 -3
  281. package/src/ol/controls/snapshots/RoutingControlRouteGen10.json +0 -58
  282. package/src/ol/controls/snapshots/RoutingControlRouteGen100.json +0 -292
  283. package/src/ol/controls/snapshots/RoutingControlRouteGen30.json +0 -69
  284. package/src/ol/controls/snapshots/RoutingControlRouteGen5.json +0 -58
  285. package/src/ol/controls/snapshots/RoutingControlRouteOSM.json +0 -759
  286. package/src/ol/controls/snapshots/RoutingControlStation1.json +0 -60
  287. package/src/ol/controls/snapshots/RoutingControlStation2.json +0 -49
  288. package/src/ol/index.js +0 -5
  289. package/src/ol/layers/Layer.js +0 -193
  290. package/src/ol/layers/Layer.test.js +0 -197
  291. package/src/ol/layers/MapboxLayer.js +0 -378
  292. package/src/ol/layers/MapboxStyleLayer.js +0 -417
  293. package/src/ol/layers/MaplibreLayer.js +0 -280
  294. package/src/ol/layers/RoutingLayer.js +0 -91
  295. package/src/ol/layers/TralisLayer.js +0 -359
  296. package/src/ol/layers/TralisLayer.test.js +0 -97
  297. package/src/ol/layers/VectorLayer.js +0 -43
  298. package/src/ol/layers/WMSLayer.js +0 -80
  299. package/src/ol/layers/WMSLayer.test.js +0 -84
  300. package/src/ol/layers/index.js +0 -8
  301. package/src/ol/styles/fullTrajectoryStyle.js +0 -51
  302. package/src/ol/styles/index.js +0 -2
  303. package/src/setupTests.js +0 -15
  304. package/webpack.config.js +0 -6
@@ -0,0 +1,151 @@
1
+ import fetch from "jest-fetch-mock";
2
+ import View from "ol/View";
3
+ import qs from "query-string";
4
+ import Map from "ol/Map";
5
+ import RoutingControl from "./RoutingControl";
6
+ import RoutingControlStation1 from "./snapshots/RoutingControlStation1.json";
7
+ import RoutingControlStation2 from "./snapshots/RoutingControlStation2.json";
8
+ import RoutingControlRouteGen5 from "./snapshots/RoutingControlRouteGen5.json";
9
+ import RoutingControlRouteGen10 from "./snapshots/RoutingControlRouteGen10.json";
10
+ import RoutingControlRouteGen30 from "./snapshots/RoutingControlRouteGen30.json";
11
+ import RoutingControlRouteGen100 from "./snapshots/RoutingControlRouteGen100.json";
12
+ import RoutingControlRouteOSM from "./snapshots/RoutingControlRouteOSM.json";
13
+ describe("RoutingControl", () => {
14
+ let map;
15
+ beforeEach(() => {
16
+ const target = document.createElement("div");
17
+ document.body.appendChild(target);
18
+ map = new Map({
19
+ target,
20
+ view: new View({
21
+ center: [0, 0],
22
+ zoom: 0
23
+ })
24
+ });
25
+ global.fetch = fetch;
26
+ });
27
+ afterEach(() => {
28
+ if (map) {
29
+ map.setTarget(null);
30
+ map = null;
31
+ }
32
+ fetch.resetMocks();
33
+ });
34
+ test("should be activate by default", () => {
35
+ const control = new RoutingControl();
36
+ expect(control.active).toBe(true);
37
+ expect(control.snapToClosestStation).toBe(false);
38
+ expect(control.useRawViaPoints).toBe(false);
39
+ });
40
+ test("launch routing and add features", (done) => {
41
+ fetch.mockResponseOnce(JSON.stringify(global.fetchRouteResponse));
42
+ const control = new RoutingControl({
43
+ url: "https://foo.ch",
44
+ apiKey: "foo"
45
+ });
46
+ control.attachToMap(map);
47
+ expect(map.getTarget().querySelector("#ol-toggle-routing")).toBeDefined();
48
+ control.viaPoints = [
49
+ [950476.4055933182, 6003322253698345e-9],
50
+ [950389.0813034325, 6003656659274571e-9]
51
+ ];
52
+ control.drawRoute(control.viaPoints).then(() => {
53
+ expect(fetch.mock.calls[0][0]).toEqual("https://foo.ch?coord-punish=1000&coord-radius=100&elevation=false&graph=osm&key=foo&mot=bus&resolve-hops=false&via=47.3739194713294%2C8.538274823394632%7C47.37595378493421%2C8.537490375951839");
54
+ expect(control.routingLayer.olLayer.getSource().getFeatures().length).toEqual(3);
55
+ done();
56
+ }).catch(() => {
57
+ });
58
+ });
59
+ test("launch routing and add features for multiple graphs", (done) => {
60
+ fetch.mockResponses([JSON.stringify(RoutingControlStation1), { status: 200 }], [JSON.stringify(RoutingControlStation2), { status: 200 }], [JSON.stringify(RoutingControlRouteGen5), { status: 200 }], [JSON.stringify(RoutingControlRouteGen10), { status: 200 }], [JSON.stringify(RoutingControlRouteGen30), { status: 200 }], [JSON.stringify(RoutingControlRouteGen100), { status: 200 }], [JSON.stringify(RoutingControlRouteOSM), { status: 200 }]);
61
+ const control = new RoutingControl({
62
+ url: "https://foo.ch/",
63
+ stopsApiUrl: "https://foo.ch/",
64
+ apiKey: "foo",
65
+ graphs: [
66
+ ["gen5", 6, 7],
67
+ ["gen10", 8],
68
+ ["gen30", 9, 10],
69
+ ["gen100", 11, 13],
70
+ ["osm", 14, 99]
71
+ ]
72
+ });
73
+ control.attachToMap(map);
74
+ control.viaPoints = ["a4dca961d199ff76", "e3666f03cba06b2b"];
75
+ control.drawRoute(control.viaPoints).then(() => {
76
+ expect(fetch.mock.calls[0][0]).toEqual("https://foo.ch/lookup/a4dca961d199ff76?key=foo");
77
+ expect(fetch.mock.calls[1][0]).toEqual("https://foo.ch/lookup/e3666f03cba06b2b?key=foo");
78
+ expect(fetch.mock.calls[2][0]).toEqual("https://foo.ch/?coord-punish=1000&coord-radius=100&elevation=false&graph=gen5&key=foo&mot=bus&resolve-hops=false&via=%21a4dca961d199ff76%7C%21e3666f03cba06b2b");
79
+ expect(fetch.mock.calls[3][0]).toEqual("https://foo.ch/?coord-punish=1000&coord-radius=100&elevation=false&graph=gen10&key=foo&mot=bus&resolve-hops=false&via=%21a4dca961d199ff76%7C%21e3666f03cba06b2b");
80
+ expect(fetch.mock.calls[4][0]).toEqual("https://foo.ch/?coord-punish=1000&coord-radius=100&elevation=false&graph=gen30&key=foo&mot=bus&resolve-hops=false&via=%21a4dca961d199ff76%7C%21e3666f03cba06b2b");
81
+ expect(fetch.mock.calls[5][0]).toEqual("https://foo.ch/?coord-punish=1000&coord-radius=100&elevation=false&graph=gen100&key=foo&mot=bus&resolve-hops=false&via=%21a4dca961d199ff76%7C%21e3666f03cba06b2b");
82
+ expect(fetch.mock.calls[6][0]).toEqual("https://foo.ch/?coord-punish=1000&coord-radius=100&elevation=false&graph=osm&key=foo&mot=bus&resolve-hops=false&via=%21a4dca961d199ff76%7C%21e3666f03cba06b2b");
83
+ expect(control.routingLayer.olLayer.getSource().getFeatures().length).toEqual(7);
84
+ done();
85
+ }).catch(() => {
86
+ });
87
+ });
88
+ test("ignores Abort Error and returns undefined", (done) => {
89
+ const control = new RoutingControl({
90
+ url: "https://foo.ch",
91
+ apiKey: "foo"
92
+ });
93
+ control.attachToMap(map);
94
+ control.viaPoints = [
95
+ [950476.4055933182, 6003322253698345e-9],
96
+ [950389.0813034325, 6003656659274571e-9]
97
+ ];
98
+ const error = new Error("Error");
99
+ error.name = "AbortError";
100
+ fetch.mockRejectOnce(error);
101
+ return control.drawRoute().then((data) => {
102
+ expect(data).toEqual([void 0]);
103
+ done();
104
+ });
105
+ });
106
+ test("calls routing api with @ before the coordinates when snapToClosestStation is true", (done) => {
107
+ fetch.mockResponses([JSON.stringify(RoutingControlStation1), { status: 200 }], [JSON.stringify(global.fetchRouteResponse), { status: 200 }]);
108
+ const control = new RoutingControl({
109
+ apiKey: "foo",
110
+ snapToClosestStation: true
111
+ });
112
+ control.attachToMap(map);
113
+ expect(map.getTarget().querySelector("#ol-toggle-routing")).toBeDefined();
114
+ control.viaPoints = [
115
+ [950476.4055933182, 6003322253698345e-9],
116
+ [950389.0813034325, 6003656659274571e-9],
117
+ "e3666f03cba06b2b"
118
+ ];
119
+ control.drawRoute(control.viaPoints).then(() => {
120
+ const params = qs.parseUrl(fetch.mock.calls[1][0]).query;
121
+ expect(params.via).toBe("@47.3739194713294,8.538274823394632|@47.37595378493421,8.537490375951839|!e3666f03cba06b2b");
122
+ done();
123
+ }).catch(() => {
124
+ });
125
+ });
126
+ test("calls routing api with raw via points", (done) => {
127
+ fetch.mockResponses([JSON.stringify(RoutingControlStation1), { status: 200 }], [JSON.stringify(RoutingControlStation2), { status: 200 }], [JSON.stringify(global.fetchRouteResponse), { status: 200 }]);
128
+ const control = new RoutingControl({
129
+ apiKey: "foo",
130
+ useRawViaPoints: true
131
+ });
132
+ control.attachToMap(map);
133
+ expect(map.getTarget().querySelector("#ol-toggle-routing")).toBeDefined();
134
+ control.viaPoints = [
135
+ "46.2,7.1",
136
+ "@46.2,7.1",
137
+ "@46.2,7$1",
138
+ "station name$2",
139
+ "station name@46.2,7",
140
+ "stationname@46.2,7.7$3",
141
+ "!stationid",
142
+ [950389, 6003656]
143
+ ];
144
+ control.drawRoute(control.viaPoints).then(() => {
145
+ const params = qs.parseUrl(fetch.mock.calls[2][0]).query;
146
+ expect(params.via).toBe("46.2,7.1|@46.2,7.1|@46.2,7$1|station name$2|station name@46.2,7|stationname@46.2,7.7$3|!stationid|47.375949774398805,8.537489645590679");
147
+ done();
148
+ }).catch(() => {
149
+ });
150
+ });
151
+ });
@@ -0,0 +1,10 @@
1
+ import { fromLonLat } from "ol/proj";
2
+ import Control from "../../common/controls/Control";
3
+ import mixin from "../../common/mixins/SearchMixin";
4
+ class StopFinderControl extends mixin(Control) {
5
+ onSuggestionClick({ geometry }) {
6
+ const coord = fromLonLat(geometry.coordinates);
7
+ this.map.getView().setCenter(coord);
8
+ }
9
+ }
10
+ export default StopFinderControl;
@@ -0,0 +1,48 @@
1
+ import fetch from "jest-fetch-mock";
2
+ import View from "ol/View";
3
+ import Map from "ol/Map";
4
+ import StopFinderControl from "./StopFinderControl";
5
+ describe("StopFinderControl", () => {
6
+ let map;
7
+ beforeEach(() => {
8
+ const target = document.createElement("div");
9
+ document.body.appendChild(target);
10
+ map = new Map({
11
+ target,
12
+ view: new View({
13
+ center: [0, 0],
14
+ zoom: 0
15
+ })
16
+ });
17
+ global.fetch = fetch;
18
+ });
19
+ afterEach(() => {
20
+ if (map) {
21
+ map.setTarget(null);
22
+ map = null;
23
+ }
24
+ fetch.resetMocks();
25
+ });
26
+ test("should be activate by default", () => {
27
+ const control = new StopFinderControl();
28
+ expect(control.active).toBe(true);
29
+ });
30
+ test("launch a search and display results", (done) => {
31
+ fetch.mockResponseOnce(JSON.stringify(global.stopsSearchResponse));
32
+ const control = new StopFinderControl({
33
+ url: "https://foo.ch",
34
+ apiKey: "foo",
35
+ apiParams: {
36
+ limit: 10,
37
+ foo: "bar"
38
+ }
39
+ });
40
+ control.attachToMap(map);
41
+ expect(control.element).toBeDefined();
42
+ control.search("foo").then(() => {
43
+ expect(fetch.mock.calls[0][0]).toEqual("https://foo.ch?foo=bar&key=foo&limit=10&q=foo");
44
+ expect(control.element.querySelector("div").querySelector("div").innerHTML).toBe("Bern");
45
+ done();
46
+ });
47
+ });
48
+ });
@@ -0,0 +1,3 @@
1
+ export { default as CopyrightControl } from "./CopyrightControl";
2
+ export { default as RoutingControl } from "./RoutingControl";
3
+ export { default as StopFinderControl } from "./StopFinderControl";
package/ol/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from "../api";
2
+ export * from "../common";
3
+ export * from "./controls";
4
+ export * from "./layers";
5
+ export * from "./styles";
@@ -0,0 +1,88 @@
1
+ import { unByKey } from "ol/Observable";
2
+ import Group from "ol/layer/Group";
3
+ import LayerCommon from "../../common/layers/Layer";
4
+ class Layer extends LayerCommon {
5
+ constructor(options) {
6
+ super(options);
7
+ if (this.olLayer) {
8
+ this.olLayer.setVisible(this.visible);
9
+ }
10
+ }
11
+ defineProperties(options) {
12
+ super.defineProperties(options);
13
+ Object.defineProperties(this, {
14
+ olLayer: { value: options.olLayer, writable: true },
15
+ olListenersKeys: {
16
+ value: []
17
+ }
18
+ });
19
+ }
20
+ attachToMap(map) {
21
+ super.attachToMap(map);
22
+ if (!this.map) {
23
+ return;
24
+ }
25
+ if (this.map && this.olLayer) {
26
+ this.map.addLayer(this.olLayer);
27
+ }
28
+ this.olListenersKeys.push(this.map.getLayers().on("remove", (evt) => {
29
+ if (evt.element === this.olLayer) {
30
+ this.detachFromMap();
31
+ }
32
+ }));
33
+ if (this.isClickActive || this.isHoverActive) {
34
+ this.toggleVisibleListeners();
35
+ this.olListenersKeys.push(this.on("change:visible", this.toggleVisibleListeners));
36
+ }
37
+ if (this.copyrights && this.olLayer) {
38
+ const attributions = this.copyrights || [];
39
+ if (this.olLayer instanceof Group) {
40
+ this.olLayer.getLayers().getArray().forEach((layer) => {
41
+ layer.getSource().setAttributions(attributions);
42
+ });
43
+ } else if (this.olLayer.getSource) {
44
+ this.olLayer.getSource().setAttributions(attributions);
45
+ }
46
+ }
47
+ }
48
+ detachFromMap() {
49
+ unByKey(this.olListenersKeys);
50
+ if (this.map && this.olLayer) {
51
+ this.map.removeLayer(this.olLayer);
52
+ }
53
+ super.detachFromMap();
54
+ }
55
+ setVisible(visible, stopPropagationDown = false, stopPropagationUp = false, stopPropagationSiblings = false) {
56
+ if (visible === this.visible) {
57
+ return;
58
+ }
59
+ super.setVisible(visible, stopPropagationDown, stopPropagationUp, stopPropagationSiblings);
60
+ if (this.olLayer) {
61
+ this.olLayer.setVisible(this.visible);
62
+ }
63
+ }
64
+ toggleVisibleListeners() {
65
+ if (this.isClickListenerKey && this.isHoverListenerKey) {
66
+ [this.isClickListenerKey, this.isHoverListenerKey].forEach((key) => {
67
+ const index = this.olListenersKeys.indexOf(key);
68
+ if (index > -1) {
69
+ this.olListenersKeys.splice(index, 1);
70
+ }
71
+ unByKey([this.isHoverListenerKey, this.isClickListenerKey]);
72
+ });
73
+ }
74
+ if (this.visible) {
75
+ if (this.isClickActive) {
76
+ this.isClickListenerKey = this.map.on("singleclick", this.onUserClickCallback);
77
+ }
78
+ if (this.isHoverActive) {
79
+ this.isHoverListenerKey = this.map.on("pointermove", this.onUserMoveCallback);
80
+ }
81
+ this.olListenersKeys.push(this.isClickListenerKey, this.isHoverListenerKey);
82
+ }
83
+ }
84
+ clone(newOptions) {
85
+ return new Layer({ ...this.options, ...newOptions });
86
+ }
87
+ }
88
+ export default Layer;
@@ -0,0 +1,174 @@
1
+ import VectorLayer from "ol/layer/Vector";
2
+ import VectorSource from "ol/source/Vector";
3
+ import Map from "ol/Map";
4
+ import Group from "ol/layer/Group";
5
+ import Layer from "./Layer";
6
+ let olLayer;
7
+ let map;
8
+ describe("Layer", () => {
9
+ beforeEach(() => {
10
+ map = new Map({});
11
+ olLayer = new VectorLayer({ source: new VectorSource() });
12
+ });
13
+ test("should initialize.", () => {
14
+ const layer = new Layer({ name: "Layer", olLayer });
15
+ expect(layer).toBeInstanceOf(Layer);
16
+ });
17
+ test("should be visible by default.", () => {
18
+ const layer = new Layer({ name: "Layer", olLayer });
19
+ expect(layer.visible).toBe(true);
20
+ });
21
+ test("should be invisible if defined.", () => {
22
+ const layer = new Layer({ name: "Layer", visible: false, olLayer });
23
+ expect(layer.visible).toBe(false);
24
+ });
25
+ test("should be invisible if set.", () => {
26
+ const layer = new Layer({ name: "Layer", olLayer });
27
+ layer.setVisible(false);
28
+ expect(layer.visible).toBe(false);
29
+ });
30
+ test("should visibility stay unchanged", () => {
31
+ const layer = new Layer({ name: "Layer", visible: false, olLayer });
32
+ layer.setVisible(false);
33
+ expect(layer.visible).toBe(false);
34
+ });
35
+ test("should return its name.", () => {
36
+ const layer = new Layer({ name: "Layer", visible: false, olLayer });
37
+ expect(layer.name).toEqual("Layer");
38
+ });
39
+ test("should call terminate on initialization.", () => {
40
+ const layer = new Layer({ name: "Layer", olLayer });
41
+ const spy = jest.spyOn(layer, "detachFromMap");
42
+ layer.attachToMap();
43
+ expect(spy).toHaveBeenCalledTimes(1);
44
+ });
45
+ test("should remove the layer when we call terminate.", () => {
46
+ const layer = new Layer({ name: "Layer", olLayer });
47
+ const spy = jest.spyOn(layer, "detachFromMap");
48
+ layer.attachToMap(map);
49
+ expect(spy).toHaveBeenCalledTimes(1);
50
+ layer.detachFromMap(map);
51
+ expect(spy).toHaveBeenCalledTimes(2);
52
+ });
53
+ test("should manage copyrights as string.", () => {
54
+ const spy = jest.spyOn(VectorSource.prototype, "setAttributions");
55
+ const layer = new Layer({ name: "Layer", copyrights: "foo", olLayer });
56
+ layer.attachToMap(map);
57
+ expect(spy).toHaveBeenCalledWith(["foo"]);
58
+ });
59
+ test("should manage copyrights as array.", () => {
60
+ const spy = jest.spyOn(VectorSource.prototype, "setAttributions");
61
+ const layer = new Layer({ name: "Layer", copyrights: ["bar"], olLayer });
62
+ layer.attachToMap(map);
63
+ expect(spy).toHaveBeenCalledWith(["bar"]);
64
+ });
65
+ test("should set attributions for Group.", () => {
66
+ const spy = jest.spyOn(VectorSource.prototype, "setAttributions");
67
+ const layer = new Layer({
68
+ name: "Layer",
69
+ copyrights: ["bar"],
70
+ olLayer: new Group({ layers: [olLayer] })
71
+ });
72
+ layer.attachToMap(map);
73
+ expect(spy).toHaveBeenCalledWith(["bar"]);
74
+ });
75
+ test("should listen for click/hover events when layer is visible by default then should not when hidden.", async () => {
76
+ global.console.error = jest.fn();
77
+ const layer = new Layer({ name: "Layer", olLayer });
78
+ expect(layer.visible).toBe(true);
79
+ const spy = jest.fn();
80
+ const spy2 = jest.fn();
81
+ layer.attachToMap(map);
82
+ layer.onHover(spy);
83
+ layer.onClick(spy2);
84
+ expect(spy).toHaveBeenCalledTimes(0);
85
+ expect(spy2).toHaveBeenCalledTimes(0);
86
+ await map.dispatchEvent({ type: "pointermove", map, coordinate: [0, 0] });
87
+ await map.dispatchEvent({ type: "singleclick", map, coordinate: [0, 0] });
88
+ expect(spy).toHaveBeenCalledTimes(1);
89
+ expect(spy2).toHaveBeenCalledTimes(1);
90
+ spy.mockReset();
91
+ spy2.mockReset();
92
+ layer.setVisible(false);
93
+ await map.dispatchEvent({ type: "pointermove", map, coordinate: [0, 0] });
94
+ await map.dispatchEvent({ type: "singleclick", map, coordinate: [0, 0] });
95
+ expect(spy).toHaveBeenCalledTimes(0);
96
+ expect(spy2).toHaveBeenCalledTimes(0);
97
+ global.console.error.mockRestore();
98
+ });
99
+ test("should not listen for click/hover events when layer is not visible by default then should not when visible.", async () => {
100
+ global.console.error = jest.fn();
101
+ const layer = new Layer({ name: "Layer", olLayer, visible: false });
102
+ expect(layer.visible).toBe(false);
103
+ const spy = jest.fn();
104
+ const spy2 = jest.fn();
105
+ layer.attachToMap(map);
106
+ layer.onHover(spy);
107
+ layer.onClick(spy2);
108
+ expect(spy).toHaveBeenCalledTimes(0);
109
+ expect(spy2).toHaveBeenCalledTimes(0);
110
+ await map.dispatchEvent({ type: "pointermove", map, coordinate: [0, 0] });
111
+ await map.dispatchEvent({ type: "singleclick", map, coordinate: [0, 0] });
112
+ expect(spy).toHaveBeenCalledTimes(0);
113
+ expect(spy2).toHaveBeenCalledTimes(0);
114
+ spy.mockReset();
115
+ spy2.mockReset();
116
+ layer.setVisible(true);
117
+ await map.dispatchEvent({ type: "pointermove", map, coordinate: [0, 0] });
118
+ await map.dispatchEvent({ type: "singleclick", map, coordinate: [0, 0] });
119
+ expect(spy).toHaveBeenCalledTimes(1);
120
+ expect(spy2).toHaveBeenCalledTimes(1);
121
+ global.console.error.mockRestore();
122
+ });
123
+ test("should not listen for click/hover events after layer.detachFromMap()", async () => {
124
+ global.console.error = jest.fn();
125
+ const layer = new Layer({ name: "Layer", olLayer, visible: true });
126
+ expect(layer.visible).toBe(true);
127
+ const spy = jest.fn();
128
+ const spy2 = jest.fn();
129
+ layer.attachToMap(map);
130
+ layer.onHover(spy);
131
+ layer.onClick(spy2);
132
+ expect(spy).toHaveBeenCalledTimes(0);
133
+ expect(spy2).toHaveBeenCalledTimes(0);
134
+ await map.dispatchEvent({
135
+ type: "pointermove",
136
+ map,
137
+ coordinate: [0, 0]
138
+ });
139
+ await map.dispatchEvent({
140
+ type: "singleclick",
141
+ map,
142
+ coordinate: [0, 0]
143
+ });
144
+ expect(spy).toHaveBeenCalledTimes(1);
145
+ expect(spy2).toHaveBeenCalledTimes(1);
146
+ spy.mockReset();
147
+ spy2.mockReset();
148
+ layer.detachFromMap(map);
149
+ await map.dispatchEvent({
150
+ type: "pointermove",
151
+ map,
152
+ coordinate: [0, 0]
153
+ });
154
+ await map.dispatchEvent({
155
+ type: "singleclick",
156
+ map,
157
+ coordinate: [0, 0]
158
+ });
159
+ expect(spy).toHaveBeenCalledTimes(0);
160
+ expect(spy2).toHaveBeenCalledTimes(0);
161
+ global.console.error.mockRestore();
162
+ });
163
+ test("should clone", () => {
164
+ const layer = new Layer({
165
+ name: "Layer",
166
+ copyrights: ["bar"],
167
+ olLayer: new Group({ layers: [olLayer] })
168
+ });
169
+ const clone = layer.clone({ name: "clone" });
170
+ expect(clone).not.toBe(layer);
171
+ expect(clone.name).toBe("clone");
172
+ expect(clone).toBeInstanceOf(Layer);
173
+ });
174
+ });
@@ -0,0 +1,203 @@
1
+ import { toLonLat } from "ol/proj";
2
+ import { Map } from "mapbox-gl";
3
+ import Source from "ol/source/Source";
4
+ import OLLayer from "ol/layer/Layer";
5
+ import GeoJSON from "ol/format/GeoJSON";
6
+ import Layer from "./Layer";
7
+ import { getMapboxMapCopyrights, getMapboxStyleUrl } from "../../common/utils";
8
+ export default class MapboxLayer extends Layer {
9
+ constructor(options = {}) {
10
+ const mbLayer = new OLLayer({
11
+ source: new Source({}),
12
+ render: (frameState) => {
13
+ if (!this.mbMap) {
14
+ console.warn("Mapbox map doesn't exist.");
15
+ return null;
16
+ }
17
+ let changed = false;
18
+ const canvas = this.mbMap.getCanvas();
19
+ const { viewState } = frameState;
20
+ const visible = this.olLayer.getVisible();
21
+ if (this.renderState.visible !== visible) {
22
+ canvas.style.display = visible ? "block" : "none";
23
+ this.renderState.visible = visible;
24
+ canvas.style.position = "absolute";
25
+ }
26
+ const opacity = this.olLayer.getOpacity();
27
+ if (this.renderState.opacity !== opacity) {
28
+ canvas.style.opacity = opacity;
29
+ this.renderState.opacity = opacity;
30
+ }
31
+ const { rotation } = viewState;
32
+ if (this.renderState.rotation !== rotation) {
33
+ this.mbMap.rotateTo(-(rotation || 0) * 180 / Math.PI, {
34
+ animate: false
35
+ });
36
+ changed = true;
37
+ this.renderState.rotation = rotation;
38
+ }
39
+ if (this.renderState.zoom !== viewState.zoom || this.renderState.center[0] !== viewState.center[0] || this.renderState.center[1] !== viewState.center[1]) {
40
+ this.mbMap.jumpTo({
41
+ center: toLonLat(viewState.center),
42
+ zoom: viewState.zoom - 1,
43
+ animate: false
44
+ });
45
+ changed = true;
46
+ this.renderState.zoom = viewState.zoom;
47
+ this.renderState.center = viewState.center;
48
+ }
49
+ const size = this.map.getSize();
50
+ if (this.renderState.size[0] !== size[0] || this.renderState.size[1] !== size[1]) {
51
+ changed = true;
52
+ this.renderState.size = size;
53
+ }
54
+ if (this.mbMap && this.mbMap.style && this.mbMap.isStyleLoaded() && changed) {
55
+ try {
56
+ if (this.mbMap._frame) {
57
+ this.mbMap._frame.cancel();
58
+ this.mbMap._frame = null;
59
+ }
60
+ this.mbMap._render();
61
+ } catch (err) {
62
+ console.warn(err);
63
+ }
64
+ }
65
+ return this.mbMap.getContainer();
66
+ }
67
+ });
68
+ super({
69
+ ...options,
70
+ olLayer: mbLayer
71
+ });
72
+ this.styleUrl = options.url;
73
+ this.apiKey = options.apiKey;
74
+ this.apiKeyName = options.apiKeyName || "key";
75
+ this.updateAttribution = this.updateAttribution.bind(this);
76
+ }
77
+ attachToMap(map) {
78
+ super.attachToMap(map);
79
+ if (!this.map || this.mbMap) {
80
+ return;
81
+ }
82
+ this.format = new GeoJSON({
83
+ featureProjection: this.map.getView().getProjection()
84
+ });
85
+ this.loadMbMap();
86
+ this.olListenersKeys.push(this.map.on("change:size", () => {
87
+ try {
88
+ if (this.mbMap) {
89
+ this.mbMap.resize();
90
+ }
91
+ } catch (err) {
92
+ console.warn(err);
93
+ }
94
+ }));
95
+ }
96
+ detachFromMap() {
97
+ if (this.mbMap) {
98
+ this.mbMap.off("idle", this.updateAttribution);
99
+ this.mbMap.triggerRepaint = () => {
100
+ };
101
+ this.mbMap.remove();
102
+ this.mbMap = null;
103
+ }
104
+ this.loaded = false;
105
+ super.detachFromMap();
106
+ }
107
+ createStyleUrl() {
108
+ return getMapboxStyleUrl(this.apiKey, this.apiKeyName, this.styleUrl);
109
+ }
110
+ loadMbMap() {
111
+ this.olListenersKeys.push(this.map.on("change:target", () => {
112
+ this.loadMbMap();
113
+ }));
114
+ if (!this.map.getTargetElement()) {
115
+ return;
116
+ }
117
+ if (!this.visible) {
118
+ this.olListenersKeys.push(this.once("change:visible", () => {
119
+ this.loadMbMap();
120
+ }));
121
+ return;
122
+ }
123
+ let [x, y] = this.map.getView().getCenter();
124
+ if (!x || !y) {
125
+ x = 0;
126
+ y = 0;
127
+ }
128
+ const container = document.createElement("div");
129
+ container.style.position = "absolute";
130
+ container.style.width = "100%";
131
+ container.style.height = "100%";
132
+ this.mbMap = new Map({
133
+ style: this.createStyleUrl(),
134
+ container,
135
+ interactive: false,
136
+ trackResize: false,
137
+ attributionControl: false,
138
+ ...this.options.mapOptions || {}
139
+ });
140
+ this.renderState = {
141
+ center: [x, y],
142
+ zoom: null,
143
+ rotation: null,
144
+ visible: null,
145
+ opacity: null,
146
+ size: [0, 0]
147
+ };
148
+ this.mbMap.once("load", () => {
149
+ this.mbMap.resize();
150
+ this.loaded = true;
151
+ this.copyrights = getMapboxMapCopyrights(this.mbMap) || [];
152
+ this.olLayer.getSource().setAttributions(this.copyrights);
153
+ this.dispatchEvent({
154
+ type: "load",
155
+ target: this
156
+ });
157
+ });
158
+ const mapboxCanvas = this.mbMap.getCanvas();
159
+ if (mapboxCanvas) {
160
+ if (this.options.tabIndex) {
161
+ mapboxCanvas.setAttribute("tabindex", this.options.tabIndex);
162
+ } else {
163
+ mapboxCanvas.removeAttribute("tabindex");
164
+ }
165
+ }
166
+ this.mbMap.on("idle", this.updateAttribution);
167
+ }
168
+ updateAttribution(evt) {
169
+ const newAttributions = getMapboxMapCopyrights(evt.target) || [];
170
+ if (this.copyrights.toString() !== newAttributions.toString()) {
171
+ this.copyrights = newAttributions;
172
+ this.olLayer.getSource().setAttributions(newAttributions);
173
+ }
174
+ }
175
+ getFeatureInfoAtCoordinate(coordinate, options) {
176
+ if (!options || !this.format || !this.mbMap || !this.mbMap.isStyleLoaded()) {
177
+ return Promise.resolve({ coordinate, features: [], layer: this });
178
+ }
179
+ let pixel = coordinate && this.mbMap.project(toLonLat(coordinate));
180
+ if (this.hitTolerance) {
181
+ const { x, y } = pixel;
182
+ pixel = [
183
+ { x: x - this.hitTolerance, y: y - this.hitTolerance },
184
+ { x: x + this.hitTolerance, y: y + this.hitTolerance }
185
+ ];
186
+ }
187
+ const features = this.mbMap.queryRenderedFeatures(pixel, options).map((feature) => {
188
+ const olFeature = this.format.readFeature(feature);
189
+ if (olFeature) {
190
+ olFeature.set("mapboxFeature", feature);
191
+ }
192
+ return olFeature;
193
+ });
194
+ return Promise.resolve({
195
+ layer: this,
196
+ features,
197
+ coordinate
198
+ });
199
+ }
200
+ clone(newOptions) {
201
+ return new MapboxLayer({ ...this.options, ...newOptions });
202
+ }
203
+ }