mobility-toolbox-js 2.0.0-beta.3 → 2.0.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.
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["webpack://mobility-toolbox-js/webpack/universalModuleDefinition","webpack://mobility-toolbox-js/webpack/bootstrap","webpack://mobility-toolbox-js/external \"ol/proj\"","webpack://mobility-toolbox-js/external \"ol/style\"","webpack://mobility-toolbox-js/external \"ol/Observable\"","webpack://mobility-toolbox-js/external \"ol/geom\"","webpack://mobility-toolbox-js/external \"ol/extent\"","webpack://mobility-toolbox-js/external \"ol/format/GeoJSON\"","webpack://mobility-toolbox-js/external \"query-string\"","webpack://mobility-toolbox-js/external \"ol/source/Source\"","webpack://mobility-toolbox-js/external \"ol/layer/Layer\"","webpack://mobility-toolbox-js/external \"ol/layer\"","webpack://mobility-toolbox-js/external \"ol/transform\"","webpack://mobility-toolbox-js/external \"ol/source\"","webpack://mobility-toolbox-js/external \"ol/Object\"","webpack://mobility-toolbox-js/external \"ol\"","webpack://mobility-toolbox-js/external \"lodash.debounce\"","webpack://mobility-toolbox-js/external \"lodash.throttle\"","webpack://mobility-toolbox-js/external \"ol/geom/GeometryType\"","webpack://mobility-toolbox-js/external \"ol/format\"","webpack://mobility-toolbox-js/external \"@turf/transform-rotate\"","webpack://mobility-toolbox-js/external \"@turf/helpers\"","webpack://mobility-toolbox-js/external \"ol/layer/Group\"","webpack://mobility-toolbox-js/external \"uuid\"","webpack://mobility-toolbox-js/external \"mapbox-gl\"","webpack://mobility-toolbox-js/external \"maplibre-gl\"","webpack://mobility-toolbox-js/external \"ol/math\"","webpack://mobility-toolbox-js/external \"ol/interaction\"","webpack://mobility-toolbox-js/external \"ol/events/condition\"","webpack://mobility-toolbox-js/external \"ol/geom/Point\"","webpack://mobility-toolbox-js/./src/common/layers/Layer.js","webpack://mobility-toolbox-js/./src/ol/layers/Layer.js","webpack://mobility-toolbox-js/./src/common/utils/getMapboxStyleUrl.js","webpack://mobility-toolbox-js/./src/common/utils/removeDuplicate.js","webpack://mobility-toolbox-js/./src/common/utils/getMapboxMapCopyrights.js","webpack://mobility-toolbox-js/./src/common/trackerConfig.js","webpack://mobility-toolbox-js/./src/common/styles/trackerDefaultStyle.js","webpack://mobility-toolbox-js/./src/ol/layers/MapboxLayer.js","webpack://mobility-toolbox-js/./src/ol/layers/RoutingLayer.js","webpack://mobility-toolbox-js/./src/common/utils/getVehiclePosition.js","webpack://mobility-toolbox-js/./src/common/Tracker.js","webpack://mobility-toolbox-js/./src/common/utils/createTrackerFilters.js","webpack://mobility-toolbox-js/./src/common/api/api.js","webpack://mobility-toolbox-js/./src/api/stops/StopsAPI.js","webpack://mobility-toolbox-js/./src/api/tralis/WebSocketConnector.js","webpack://mobility-toolbox-js/./src/api/tralis/TralisAPIUtils.js","webpack://mobility-toolbox-js/./src/api/tralis/TralisAPI.js","webpack://mobility-toolbox-js/./src/common/mixins/TralisLayerMixin.js","webpack://mobility-toolbox-js/./src/ol/styles/fullTrajectoryStyle.js","webpack://mobility-toolbox-js/./src/ol/styles/fullTrajectoryDelayStyle.js","webpack://mobility-toolbox-js/./src/ol/layers/TralisLayer.js","webpack://mobility-toolbox-js/./src/ol/layers/VectorLayer.js","webpack://mobility-toolbox-js/./src/ol/layers/WMSLayer.js","webpack://mobility-toolbox-js/./src/common/controls/Control.js","webpack://mobility-toolbox-js/./src/common/mixins/CopyrightMixin.js","webpack://mobility-toolbox-js/./src/ol/controls/CopyrightControl.js","webpack://mobility-toolbox-js/./src/common/mixins/SearchMixin.js","webpack://mobility-toolbox-js/./src/ol/controls/StopFinderControl.js","webpack://mobility-toolbox-js/./src/mapbox/utils.js","webpack://mobility-toolbox-js/./src/mapbox/layers/TralisLayer.js","webpack://mobility-toolbox-js/./src/mapbox/layers/Layer.js","webpack://mobility-toolbox-js/./src/mapbox/controls/CopyrightControl.js","webpack://mobility-toolbox-js/./src/index.js"],"names":["root","factory","exports","module","define","amd","this","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","require","Layer","options","defineProperties","onClick","onHover","copyrights","onUserClickCallback","onUserMoveCallback","isQueryable","isClickActive","isHoverActive","children","visible","properties","isBaseLayer","hitTolerance","uid","uuid","dfltName","toLowerCase","writable","isMobilityLayer","set","newCopyrights","arrValue","Array","isArray","undefined","map","clickCallbacks","hoverCallbacks","terminate","dispatchEvent","type","target","stopPropagationDown","stopPropagationUp","stopPropagationSiblings","filter","child","find","coordinate","console","error","Promise","resolve","layer","features","callback","Error","includes","push","idx","indexOf","splice","evt","emptyFeatureInfo","event","length","getFeatureInfoAtCoordinate","then","featureInfo","forEach","catch","Observable","olLayer","setVisible","olListenersKeys","addLayer","getLayers","on","element","toggleVisibleListeners","attributions","Group","getArray","getSource","setAttributions","unByKey","removeLayer","isClickListenerKey","isHoverListenerKey","index","newOptions","LayerCommon","getMapboxStyleUrl","apiKey","apiKeyName","styleUrl","parsedStyle","qs","parseUrl","query","stringifyUrl","warn","removeDuplicate","array","arrWithoutEmptyValues","val","trim","lowerCasesValues","str","Set","uniqueStr","getMapboxMapCopyrights","style","sourceCaches","values","sourceCache","used","source","attribution","concat","replace","split","trackerRadiusMapping","0","1","2","3","4","5","6","7","8","9","types","bgColors","textColors","timeSteps","getTypeIndex","findIndex","test","getBgColor","typeIdx","e","getDelayColor","delayInMs","cancelled","isDelayText","createCanvas","width","height","canvas","document","createElement","cacheDelayBg","cacheDelayText","cacheCircle","cacheText","styleCache","trajectory","viewState","hoverVehicleId","selectedVehicleId","useDelayStyle","delayOutlineColor","delayDisplay","zoom","pixelRatio","line","id","train_id","delay","operatorProvidesRealtime","operator_provides_realtime_journey","textColor","text_color","color","hover","selected","radius","getRadius","Math","min","floor","isDisplayStrokeAndDelay","mustDrawText","circleFillColor","margin","radiusDelay","markerSize","size","origin","ctx","getContext","delayBg","beginPath","arc","PI","fillStyle","fill","getDelayBgCanvas","drawImage","fontSize","max","text","String","fromCodePoint","rounded","round","getDelayText","delayText","font","delayColor","textAlign","textBaseline","strokeStyle","lineWidth","strokeText","fillText","getDelayTextCanvas","circle","hasStroke","hasDash","setLineDash","stroke","getCircleCanvas","textSize","fillColor","strokeColor","save","restore","getTextCanvas","newText","measureText","getTextSize","getTextColor","MapboxLayer","mbLayer","OLLayer","Source","render","frameState","mbMap","changed","getCanvas","getVisible","renderState","display","position","opacity","getOpacity","rotation","rotateTo","animate","center","jumpTo","toLonLat","getSize","isStyleLoaded","_frame","cancel","_render","err","getContainer","url","updateAttribution","format","GeoJSON","featureProjection","getView","getProjection","loadMbMap","resize","off","triggerRepaint","remove","loaded","getTargetElement","getCenter","x","y","container","Map","createStyleUrl","interactive","trackResize","attributionControl","mapOptions","once","mapboxCanvas","tabIndex","setAttribute","removeAttribute","newAttributions","toString","pixel","project","queryRenderedFeatures","feature","olFeature","readFeature","circleStyle","Circle","Fill","Stroke","Style","image","lineDash","getVehiclePosition","now","noInterpolate","coord","timeIntervals","time_intervals","geometry","olGeometry","getType","GeomType","POINT","getCoordinates","LINE_STRING","intervals","firstInterval","lastInterval","getFirstCoordinate","getLastCoordinate","j","start","startFrac","end","endFrac","geomFrac","getCoordinateAt","Tracker","trajectories","time","Date","resolution","context","clearRect","hoverVehicleImg","hoverVehiclePx","hoverVehicleWidth","hoverVehicleHeight","selectedVehicleImg","selectedVehiclePx","selectedVehicleWidth","selectedVehicleHeight","coordinateToPixelTransform","compose","nbRendered","timeOffset","rotationIcon","px","apply","vehicleImg","imgWidth","imgHeight","nbTrajectoriesRendered","createFilters","route","operator","regexLine","filterList","regexLineList","item","some","regexStr","RegExp","lineList","toUpperCase","linee","lineName","routeList","parseInt","routeId","routeIdentifier","operatorList","op","API","path","params","config","urlParams","clone","keys","fetch","stringify","response","json","data","reject","BaseObject","StopsAPI","abortController","signal","featureCollection","WebSocketConnector","method","reqStr","channel","args","closed","websocket","readyState","CLOSED","closing","CLOSING","connecting","CONNECTING","open","OPEN","messagesOnOpen","subscriptions","subscribed","onOpen","close","WebSocket","subscribePreviousSubscriptions","addEventListener","onclose","message","send","cb","errorCb","unlisten","onMessage","JSON","parse","content","client_reference","onMessageCb","onErrorCb","removeEventListener","getRequestString","listen","quiet","subcr","newSubscr","toRemove","subscr","subscribe","getModeSuffix","modes","SCHEMATIC","compareDepartures","a","b","sortByMinArrivalTime","topStates","aTop","has_fzo","state","bTop","aDuration","bDuration","min_arrival_time","getTime","cleanStopTime","stations","station","arrivalTimeWithDelay","arrivalTime","departureTime","departureTimeWithDelay","arrivalDelay","TralisModes","RAW","TOPOGRAPHIC","TralisAPI","subscribedStationUic","departureUpdateTimeout","maxDepartureAge","extraGeoms","prefix","opt","projection","bbox","buffer","conn","newUrl","newProjection","newBbox","join","newBuffer","pingIntervalMs","reconnectTimeoutMs","connect","onClose","window","clearInterval","pingInterval","setInterval","clearTimeout","reconnectTimeout","setTimeout","onSuccess","onError","suffix","unsubscribe","depObject","departures","k","sort","future","setMinutes","getMinutes","past","departureArray","platformsBoarding","previousDeparture","platform","to","abs","unshift","stationId","unsubscribeDepartures","departureObject","tDiff","timestamp","timediff","call_id","filterDepartures","uic","stationUpdateTimeout","unsubscribeStations","extraGeom","ref","unsubscribeTrajectory","unsubscribeDeletedVehicles","generalizationLevel","ids","promises","getFullTrajectory","all","unsubscribeFullTrajectory","log","stopSequence","getStopSequence","fullTrajectoryUpdateTimeout","unsubscribeStopSequence","unsubscribeHealthCheck","TralisLayerMixin","Base","debug","api","tenant","minZoomNonTrain","minZoomInterpolation","generalizationLevelByZoom","10","11","12","13","isUpdateBboxOnMoveEnd","throttleRenderTrajectories","throttle","renderTrajectoriesInternal","leading","trailing","debounceRenderTrajectories","debounce","maxWait","onFeatureHover","onFeatureClick","onTrajectoryMessage","onDeleteTrajectoryMessage","onDocumentVisibilityChange","regexPublishedLineName","publishedLineName","tripNumber","speed","live","initTrackerOptions","currSpeed","currTime","isTrackerLayer","trackerDefaultStyle","newSpeed","tracker","newTime","renderTrajectories","renderedTrajectories","devicePixelRatio","useRequestAnimationFrame","useThrottle","useDebounce","newPublishedLineName","updateFilters","newTripNumber","newOperator","newRegex","visibilityRef","stop","startUpdateTime","subscribeTrajectory","subscribeDeletedVehicles","setBbox","stopUpdateTime","updateTimeDelay","getRefreshTimeInMs","updateTimeInterval","iconScale","requestId","cancelAnimationFrame","requestAnimationFrame","extent","purgeTrajectory","roundedZoom","timeStep","nextTick","nextThrottleTick","filterFc","nb","ext","vehicles","containsCoordinate","vehicle","fullTrajectory","bounds","intersects","removeTrajectory","hidden","timeSinceUpdate","time_since_update","rawCoordinates","raw_coordinates","coordinates","fromLonLat","readGeometry","addTrajectory","selectedVehicle","parameters","location","search","publishedName","borderStyle","zIndex","fullTrajectorystyle","lineColor","TralisLayer","layers","VectorLayer","VectorSource","fullTrajectoryStyle","transformContainer","appendChild","top","left","transformOrigin","renderedViewState","renderedCenter","renderedResolution","renderedRotation","pixelCenterRendered","getPixelFromCoordinate","pixelCenter","transform","composeCssTransform","vectorLayer","view","getAnimating","getInteracting","getZoom","currentZoom","onZoomEnd","onMoveEnd","getImageData","calculateExtent","getResolution","getRotation","highlightTrajectory","cursor","clear","newExtent","newZoom","readFeatures","addFeatures","mixin","getFeaturesAtPixel","layerFilter","WMSLayer","AbortController","getFeatureInfoUrl","info_format","query_layers","getParams","abort","resp","Control","active","newActive","activate","deactivate","parentNode","removeChild","targett","createDefaultElement","CopyrightMixin","innerHTML","getCopyrights","assign","bottom","right","padding","getMercatorResolution","getBounds","toArray","xResolution","getWidth","yResolution","getHeight","getSourceCoordinates","leftTop","unproject","leftBottom","rightBottom","rightTop","lng","lat","onLoad","onMove","onVisibilityChange","beforeId","layout","visibility","paint","listeners","listener","getLayer","removeSource","addSource","lngLat","coord0","transformRotate","point","getBearing","pivot","coord1","res","getMercatorExtent","getOlZoom","setCoordinates","getCanvasContainer","onChangeVisibleKey","transformExtent","mapbox","mbTralisLayer","ol","olWMSLayer","olMapboxLayer","olTralisLayer","olVectorLayer"],"mappings":"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","file":"index.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"mobility-toolbox-js\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"mobility-toolbox-js\"] = factory();\n\telse\n\t\troot[\"mobility-toolbox-js\"] = factory();\n})(this, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 27);\n","module.exports = require(\"ol/proj\");","module.exports = require(\"ol/style\");","module.exports = require(\"ol/Observable\");","module.exports = require(\"ol/geom\");","module.exports = require(\"ol/extent\");","module.exports = require(\"ol/format/GeoJSON\");","module.exports = require(\"query-string\");","module.exports = require(\"ol/source/Source\");","module.exports = require(\"ol/layer/Layer\");","module.exports = require(\"ol/layer\");","module.exports = require(\"ol/transform\");","module.exports = require(\"ol/source\");","module.exports = require(\"ol/Object\");","module.exports = require(\"ol\");","module.exports = require(\"lodash.debounce\");","module.exports = require(\"lodash.throttle\");","module.exports = require(\"ol/geom/GeometryType\");","module.exports = require(\"ol/format\");","module.exports = require(\"@turf/transform-rotate\");","module.exports = require(\"@turf/helpers\");","module.exports = require(\"ol/layer/Group\");","module.exports = require(\"uuid\");","module.exports = require(\"mapbox-gl\");","module.exports = require(\"maplibre-gl\");","module.exports = require(\"ol/math\");","module.exports = require(\"ol/interaction\");","module.exports = require(\"ol/events/condition\");","module.exports = require(\"ol/geom/Point\");","import Observable from 'ol/Observable';\nimport { v4 as uuid } from 'uuid';\n\n/**\n * A class representing a layer to display on map.\n *\n * @example\n * const layer = new Layer({\n * name: 'myLayer',\n * });\n *\n * @classproperty {string} name - Name of the layer\n * @classproperty {string} key - Identifier of the layer. Must be unique.\n * @classproperty {string[]} copyrights - Array of copyrights.\n * @classproperty {boolean} isBaseLayer - Define if the layer is a base layer. Read-only.\n * @classproperty {boolean} isQueryable - Define if the layer can be queried. If false, it will set isHoverActive and isClickActive to false. Read-only.\n * @classproperty {boolean} isClickActive - If true feature information will be queried on user click event. See inherited layers for more informations. Read-only.\n * @classproperty {boolean} isHoverActive - If true feature information will be queried on pointer move event. See inherited layers for more informations. Read-only.\n * @classproperty {boolean} isMobilityLayer - Custom property for duck typing since `instanceof` is not working when the instance was created on different bundles. Read-only.\n * @classproperty {Layer[]} children - List of children.\n * @classproperty {boolean} visible - Define if the layer is visible or not.\n * @classproperty {number} hitTolerance - Hit-detection tolerance in css pixels. Pixels inside the radius around the given position will be checked for features.\n * @classproperty {Object} properties - Custom properties.\n * @classproperty {ol/Map~Map|mapboxgl.Map} map - The map where the layer is displayed.\n */\nexport default class Layer extends Observable {\n /**\n * Constructor\n *\n * @param {Object} options\n * @param {string} [options.name=uuid()] Layer name. Default use a generated uuid.\n * @param {string} [options.key=uuid().toLowerCase()] Layer key, will use options.name.toLowerCase() if not specified.\n * @param {string[]} [options.copyrights=undefined] Array of copyrights.\n * @param {Array<Layer>} [options.children=[]] Sublayers.\n * @param {Object} [options.properties={}] Application-specific layer properties.\n * @param {boolean} [options.visible=true] If true this layer is visible on the map.\n * @param {boolean} [options.isBaseLayer=false] If true this layer is a baseLayer.\n * @param {boolean} [options.isQueryable=true] Define if the layer can be queried. If false, it will also set isHoverActive and isClickActive to false. Read-only.\n * @param {boolean} [options.isClickActive=true] If true feature information will be queried on click event. See inherited layers for more informations. Read-only.\n * @param {boolean} [options.isHoverActive=true] If true feature information will be queried on pointer move event. See inherited layers for more informations. Read-only.\n * @param {number} [options.hitTolerance=5] Hit-detection tolerance in css pixels. Pixels inside the radius around the given position will be checked for features.\n */\n constructor(options = {}) {\n super();\n this.defineProperties(options);\n\n // Add mouse event callbacks\n const { onClick, onHover } = options;\n\n if (onHover) {\n this.onHover(onHover);\n }\n\n if (onClick) {\n this.onClick(onClick);\n }\n\n // This if is very important if you remove it you break the copyright control.\n if (options.copyrights) {\n /** @ignore */\n this.copyrights = options.copyrights;\n }\n\n /** @ignore */\n this.onUserClickCallback = this.onUserClickCallback.bind(this);\n\n /** @ignore */\n this.onUserMoveCallback = this.onUserMoveCallback.bind(this);\n }\n\n /**\n * Define layer's properties.\n *\n * @ignore\n */\n defineProperties(options) {\n const {\n name,\n key,\n children,\n visible,\n properties,\n isBaseLayer,\n isQueryable,\n isClickActive,\n isHoverActive,\n hitTolerance,\n } = {\n isQueryable: true,\n isClickActive: true,\n isHoverActive: true,\n ...options,\n };\n const uid = uuid();\n const dfltName = name || uid;\n Object.defineProperties(this, {\n // options is used for clone function.\n options: {\n value: options,\n },\n name: {\n value: dfltName,\n },\n key: {\n value: key || dfltName.toLowerCase(),\n },\n isBaseLayer: {\n value: !!isBaseLayer,\n },\n isQueryable: {\n value: !!isQueryable,\n writable: true,\n },\n isClickActive: {\n value: !!isQueryable && !!isClickActive,\n writable: true,\n },\n isHoverActive: {\n value: !!isQueryable && !!isHoverActive,\n writable: true,\n },\n hitTolerance: {\n value: hitTolerance || 5,\n writable: true,\n },\n // Custom property for duck typing since `instanceof` is not working\n // when the instance was created on different bundles.\n isMobilityLayer: {\n value: true,\n },\n children: {\n value: children || [],\n writable: true,\n },\n copyrights: {\n get: () => this.get('copyrights'),\n set: (newCopyrights) => {\n const arrValue = !Array.isArray(newCopyrights)\n ? [newCopyrights]\n : newCopyrights;\n this.set('copyrights', arrValue);\n },\n },\n visible: {\n value: visible === undefined ? true : visible,\n writable: true,\n },\n properties: {\n value: { ...(properties || {}) },\n },\n map: {\n writable: true,\n },\n /**\n * Callback function when a user click on a feature.\n */\n clickCallbacks: {\n value: [],\n },\n /**\n * Callback function when a user hover on a feature.\n */\n hoverCallbacks: {\n value: [],\n },\n });\n }\n\n /**\n * Initialize the layer with the map passed in parameters.\n *\n * @param {ol/Map~Map|mapboxgl.Map} map A map.\n */\n init(map) {\n this.terminate();\n /** @ignore */\n this.map = map;\n }\n\n /**\n * Terminate what was initialized in init function. Remove layer, events...\n */\n // eslint-disable-next-line class-methods-use-this\n terminate() {}\n\n /**\n * Get a layer property.\n *\n * @param {string} name Property name.\n * @return {property} Property\n */\n get(name) {\n return this.properties[name];\n }\n\n /**\n * Set a layer property.\n *\n * @param {string} name Property name.\n * @param {string} value Value.\n */\n set(name, value) {\n if (value !== this.properties[name]) {\n this.properties[name] = value;\n this.dispatchEvent({\n type: `change:${name}`,\n target: this,\n });\n }\n }\n\n /**\n * Change the visibility of the layer\n *\n * @param {boolean} visible Defines the visibility of the layer\n * @param {boolean} [stopPropagationDown]\n * @param {boolean} [stopPropagationUp]\n * @param {boolean} [stopPropagationSiblings]\n */\n setVisible(\n visible,\n stopPropagationDown = false,\n stopPropagationUp = false,\n stopPropagationSiblings = false,\n ) {\n if (visible === this.visible) {\n return;\n }\n\n /** @ignore */\n this.visible = visible;\n\n this.dispatchEvent({\n type: 'change:visible',\n target: this,\n stopPropagationDown,\n stopPropagationUp,\n stopPropagationSiblings,\n });\n }\n\n /**\n * Returns an array with visible child layers\n *\n * @return {Layer[]} Visible children\n */\n getVisibleChildren() {\n return this.children.filter((child) => child.visible);\n }\n\n /**\n * Checks whether the layer has child layers with visible set to True\n *\n * @return {boolean} True if the layer has visible child layers\n * @deprecated\n */\n hasVisibleChildren() {\n return !!this.children.find((child) => child.visible === true);\n }\n\n /**\n * Request feature information for a given coordinate.\n * This function must be implemented by inheriting layers.\n *\n * @param {ol/coordinate~Coordinate} coordinate Coordinate.\n * @param {Object} options Some options. See child classes to see which are supported.\n * @return {Promise<FeatureInfo>} An empty response.\n */\n // eslint-disable-next-line no-unused-vars\n getFeatureInfoAtCoordinate(coordinate, options) {\n // eslint-disable-next-line no-console\n console.error(\n 'getFeatureInfoAtCoordinate must be implemented by inheriting layers',\n this.key,\n );\n\n // No response so we modify the properties accordingly, to avoid spaming the console.\n this.isQueryable = false;\n // this.isClickActive = false;\n // this.isHoverActive = false;\n\n // This layer returns no feature info.\n // The function is implemented by inheriting layers.\n return Promise.resolve({\n layer: this,\n features: [],\n coordinate,\n });\n }\n\n /**\n * Listens to click events on the layer.\n * @param {function} callback Callback function, called with the clicked\n * features,\n * the layer instance and the click event.\n */\n onClick(callback) {\n if (typeof callback === 'function') {\n if (!this.clickCallbacks.includes(callback)) {\n this.clickCallbacks.push(callback);\n }\n } else {\n throw new Error('onClick callback must be of type function:', callback);\n }\n }\n\n /**\n * Unlistens to click events on the layer.\n * @param {function} callback Callback function, called with the clicked\n * features,\n * the layer instance and the click event.\n */\n unClick(callback) {\n if (typeof callback === 'function') {\n const idx = this.clickCallbacks.indexOf(callback);\n if (idx > -1) {\n this.clickCallbacks.splice(idx, 1);\n }\n }\n }\n\n /**\n * Function triggered when the user click the map.\n * @private\n */\n onUserClickCallback(evt) {\n const emptyFeatureInfo = {\n features: [],\n layer: this,\n coordinate: evt.coordinate,\n event: evt,\n };\n\n if (!this.isClickActive || !this.clickCallbacks.length) {\n return Promise.resolve(emptyFeatureInfo);\n }\n\n return this.getFeatureInfoAtCoordinate(evt.coordinate)\n .then((featureInfo) => {\n const { features, layer, coordinate } = featureInfo;\n this.clickCallbacks.forEach((callback) =>\n callback(features, layer, coordinate),\n );\n return featureInfo;\n })\n .catch(() => emptyFeatureInfo);\n }\n\n /**\n * Listens to hover events on the layer.\n * @param {function} callback Callback function, called with the clicked\n * features, the layer instance and the click event.\n */\n onHover(callback) {\n if (typeof callback === 'function') {\n if (!this.hoverCallbacks.includes(callback)) {\n this.hoverCallbacks.push(callback);\n }\n } else {\n throw new Error('callback must be of type function.');\n }\n }\n\n /**\n * Unlistens to hover events on the layer.\n * @param {function} callback Callback function, called with the hovered\n * features, the layer instance and the click event.\n */\n unHover(callback) {\n if (typeof callback === 'function') {\n const idx = this.hoverCallbacks.indexOf(callback);\n if (idx > -1) {\n this.hoverCallbacks.splice(idx, 1);\n }\n }\n }\n\n /**\n * Function triggered when the user move the cursor.\n * @private\n */\n onUserMoveCallback(evt) {\n const emptyFeatureInfo = {\n features: [],\n layer: this,\n coordinate: evt.coordinate,\n event: evt,\n };\n\n if (!this.isHoverActive || !this.hoverCallbacks.length) {\n return Promise.resolve(emptyFeatureInfo);\n }\n\n return this.getFeatureInfoAtCoordinate(evt.coordinate)\n .then((featureInfo) => {\n const { features, layer, coordinate } = featureInfo;\n this.hoverCallbacks.forEach((callback) =>\n callback(features, layer, coordinate),\n );\n return featureInfo;\n })\n .catch(() => emptyFeatureInfo);\n }\n}\n","import { unByKey } from 'ol/Observable';\nimport Group from 'ol/layer/Group';\nimport LayerCommon from '../../common/layers/Layer';\n\n/**\n * A class representing a layer to display on an OpenLayers map.\n *\n * @example\n * import { Layer } from 'mobility-toolbox-js/ol';\n *\n * const layer = new Layer({\n * olLayer: ...,\n * });\n *\n * @see <a href=\"/example/ol-map\">Map example</a>\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass Layer extends LayerCommon {\n /**\n * Constructor.\n *\n * @param {Object} options\n * @param {ol/layer/Layer~Layer} options.olLayer The layer (required).\n * @param {string} [options.name=uuid()] Layer name. Default use a generated uuid.\n * @param {string} [options.key=uuid().toLowerCase()] Layer key, will use options.name.toLowerCase() if not specified.\n * @param {string} [options.copyright=undefined] Copyright-Statement.\n * @param {Array<Layer>} [options.children=[]] Sublayers.\n * @param {Object} [options.properties={}] Application-specific layer properties.\n * @param {boolean} [options.visible=true] If true this layer is the currently visible layer on the map.\n * @param {boolean} [options.isBaseLayer=false] If true this layer is a baseLayer.\n * @param {boolean} [options.isQueryable=true] If true feature information can be queried by the react-spatial LayerService. Default is true.\n * @param {boolean} [options.isClickActive=true] If true feature information will be queried on 'singleclick' event. All results will be passed to function registered using `onClick` function. Default is true.\n */\n constructor(options) {\n super(options);\n\n if (this.olLayer) {\n this.olLayer.setVisible(this.visible);\n }\n }\n\n /**\n * Define layer's properties.\n *\n * @ignore\n */\n defineProperties(options) {\n super.defineProperties(options);\n Object.defineProperties(this, {\n olLayer: { value: options.olLayer, writable: true },\n olListenersKeys: {\n value: [],\n },\n });\n }\n\n /**\n * Initialize the layer and listen to feature clicks.\n * @param {ol/Map~Map} map\n */\n init(map) {\n super.init(map);\n\n if (!this.map) {\n return;\n }\n\n if (this.map && this.olLayer) {\n this.map.addLayer(this.olLayer);\n }\n\n this.olListenersKeys.push(\n this.map.getLayers().on('remove', (evt) => {\n if (evt.element === this.olLayer) {\n this.terminate();\n }\n }),\n );\n\n if (this.isClickActive || this.isHoverActive) {\n this.toggleVisibleListeners();\n this.olListenersKeys.push(\n this.on('change:visible', this.toggleVisibleListeners),\n );\n }\n\n // We set the copyright to the source used by the layer.\n if (this.copyrights && this.olLayer) {\n const attributions = this.copyrights || [];\n if (this.olLayer instanceof Group) {\n this.olLayer\n .getLayers()\n .getArray()\n .forEach((layer) => {\n layer.getSource().setAttributions(attributions);\n });\n } else if (this.olLayer.getSource) {\n this.olLayer.getSource().setAttributions(attributions);\n }\n }\n }\n\n /**\n * Terminate what was initialized in init function. Remove layer, events...\n */\n terminate() {\n unByKey(this.olListenersKeys);\n\n if (this.map && this.olLayer) {\n this.map.removeLayer(this.olLayer);\n }\n\n super.terminate();\n }\n\n /**\n * Change the visibility of the layer\n *\n * @param {boolean} visible Defines the visibility of the layer\n * @param {boolean} [stopPropagationDown]\n * @param {boolean} [stopPropagationUp]\n * @param {boolean} [stopPropagationSiblings]\n */\n setVisible(\n visible,\n stopPropagationDown = false,\n stopPropagationUp = false,\n stopPropagationSiblings = false,\n ) {\n if (visible === this.visible) {\n return;\n }\n\n super.setVisible(\n visible,\n stopPropagationDown,\n stopPropagationUp,\n stopPropagationSiblings,\n );\n\n if (this.olLayer) {\n this.olLayer.setVisible(this.visible);\n }\n }\n\n /**\n * Toggle listeners needed when a layer is avisible or not.\n * @private\n */\n toggleVisibleListeners() {\n // Remove previous event\n if (this.isClickListenerKey && this.isHoverListenerKey) {\n [this.isClickListenerKey, this.isHoverListenerKey].forEach((key) => {\n const index = this.olListenersKeys.indexOf(key);\n if (index > -1) {\n this.olListenersKeys.splice(index, 1);\n }\n unByKey([this.isHoverListenerKey, this.isClickListenerKey]);\n });\n }\n\n if (this.visible) {\n if (this.isClickActive) {\n this.isClickListenerKey = this.map.on(\n 'singleclick',\n this.onUserClickCallback,\n );\n }\n if (this.isHoverActive) {\n this.isHoverListenerKey = this.map.on(\n 'pointermove',\n this.onUserMoveCallback,\n );\n }\n this.olListenersKeys.push(\n this.isClickListenerKey,\n this.isHoverListenerKey,\n );\n }\n }\n\n /**\n * Create a copy of the Layer.\n * @param {Object} newOptions Options to override\n * @return {Layer} A Layer\n */\n clone(newOptions) {\n return new Layer({ ...this.options, ...newOptions });\n }\n}\nexport default Layer;\n","import qs from 'query-string';\n\n/**\n * Return the styleUrl with apiKey parameters set.\n * @param {string} apiKey apiKey value for the mapbox request.\n * @param {string} apiKeyName parameter name for apiKey in the mapbox request.\n * @param {string} styleUrl mapbox styleUrl value.\n * @ignore\n */\nconst getMapboxStyleUrl = (apiKey, apiKeyName, styleUrl) => {\n if (apiKey === false) {\n return styleUrl;\n }\n const parsedStyle = qs.parseUrl(styleUrl);\n if (!apiKey && parsedStyle.query[apiKeyName]) {\n return styleUrl;\n }\n if (!apiKey) {\n // eslint-disable-next-line no-console\n console.warn(`No apiKey is defined for request to ${styleUrl}`);\n return null;\n }\n return qs.stringifyUrl({\n ...parsedStyle,\n query: {\n ...parsedStyle.query,\n [apiKeyName]: apiKey,\n },\n });\n};\n\nexport default getMapboxStyleUrl;\n","/**\n * This function remove duplicates lower case string value of an array.\n * It removes also null, undefined or non string values.\n *\n * @param {array} array Array of values.\n * @ignore\n */\nconst removeDuplicate = (array) => {\n const arrWithoutEmptyValues = array.filter(\n (val) => val !== undefined && val !== null && val.trim && val.trim(),\n );\n const lowerCasesValues = arrWithoutEmptyValues.map((str) =>\n str.toLowerCase(),\n );\n const uniqueLowerCaseValues = [...new Set(lowerCasesValues)];\n const uniqueValues = uniqueLowerCaseValues.map((uniqueStr) =>\n arrWithoutEmptyValues.find((str) => str.toLowerCase() === uniqueStr),\n );\n return uniqueValues;\n};\n\nexport default removeDuplicate;\n","import removeDuplicate from './removeDuplicate';\n\n/**\n * Return the copyright a Mapbox map.\n * @param {mapboxgl.Map} map A Mapbox map\n * @ignore\n */\nconst getMapboxMapCopyrights = (map) => {\n if (!map || !map.style) {\n return [];\n }\n const { sourceCaches } = map.style;\n let copyrights = [];\n\n Object.values(sourceCaches).forEach((sourceCache) => {\n if (sourceCache.used) {\n const source = sourceCache.getSource();\n const attribution =\n source.attribution || (source.options && source.options.attribution);\n\n if (attribution) {\n copyrights = copyrights.concat(\n attribution.replace(/&copy;/g, '©').split(/(<a.*?<\\/a>)/),\n );\n }\n }\n });\n\n return removeDuplicate(copyrights);\n};\n\nexport default getMapboxMapCopyrights;\n","const trackerRadiusMapping = {\n 0: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 1: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 2: [0, 0, 0, 0, 0, 2, 2, 3, 7, 7, 7, 12, 15, 15, 15, 15, 15],\n 3: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 4: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 5: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 6: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 7: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 8: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 9: [0, 0, 0, 0, 0, 2, 2, 3, 7, 7, 7, 12, 15, 15, 15, 15, 15],\n};\n\n/**\n * Trajserv value: 'Tram', 'Subway / Metro / S-Bahn', 'Train', 'Bus', 'Ferry', 'Cable Car', 'Gondola', 'Funicular', 'Long distance bus', 'Rail',\n * New endpoint use Rail instead of Train.\n * New tracker values: null, \"tram\", \"subway\", \"rail\", \"bus\", \"ferry\", \"cablecar\", \"gondola\", \"funicular\", \"coach\".\n *\n * @ignore\n */\nexport const types = [\n /^Tram/i,\n /^Subway( \\/ Metro \\/ S-Bahn)?/i,\n /^Train/i,\n /^Bus/i,\n /^Ferry/i,\n /^Cable ?Car/i,\n /^Gondola/i,\n /^Funicular/i,\n /^(Long distance bus|coach)/i,\n /^Rail/i, // New endpoint use Rail instead of Train.\n];\n\n/**\n * @ignore\n */\nexport const bgColors = [\n '#ffb400',\n '#ff5400',\n '#ff8080',\n '#ea0000',\n '#3000ff',\n '#ffb400',\n '#41a27b',\n '#00d237',\n '#b5b5b5',\n '#ff8080',\n];\n\n/**\n * @ignore\n */\nexport const textColors = [\n '#000000',\n '#ffffff',\n '#000000',\n '#ffffff',\n '#ffffff',\n '#000000',\n '#ffffff',\n '#000000',\n '#000000',\n '#000000',\n];\n\n/**\n * @ignore\n */\nexport const timeSteps = [\n 100000, 50000, 40000, 30000, 20000, 15000, 10000, 5000, 2000, 1000, 400, 300,\n 250, 180, 90, 60, 50, 50, 50, 50, 50,\n];\n\n/**\n * @ignore\n */\nexport const getTypeIndex = (type) => {\n if (typeof type === 'string') {\n return types.findIndex((t) => t.test(type));\n }\n return type;\n};\n\n/**\n * @ignore\n */\nexport const getRadius = (type, zoom) => {\n try {\n const typeIdx = getTypeIndex(type || 0);\n return trackerRadiusMapping[typeIdx][zoom];\n } catch (e) {\n return 1;\n }\n};\n\n/**\n * @ignore\n */\nexport const getBgColor = (type = 0) => {\n try {\n const typeIdx = getTypeIndex(type);\n return bgColors[typeIdx];\n } catch (e) {\n return 1;\n }\n};\n\n/**\n * @ignore\n */\nexport const getTextColor = (type = 0) => {\n try {\n const typeIdx = getTypeIndex(type);\n return textColors[typeIdx];\n } catch (e) {\n return 1;\n }\n};\n\n/**\n * @ignore\n */\nexport const getTextSize = (ctx, markerSize, text, fontSize) => {\n ctx.font = `bold ${fontSize}px Arial`;\n let newText = ctx.measureText(text);\n\n const maxiter = 25;\n let i = 0;\n\n while (newText.width > markerSize - 6 && i < maxiter) {\n // eslint-disable-next-line no-param-reassign\n fontSize -= 0.5;\n ctx.font = `bold ${fontSize}px arial, sans-serif`;\n newText = ctx.measureText(text);\n i += 1;\n }\n return fontSize;\n};\n\n/**\n * @ignore\n * @param {number} delayInMs Delay in milliseconds.\n * @param {boolean} cancelled true if the journey is cancelled.\n * @param {boolean} isDelayText true if the color is used for delay text of the symbol.\n */\nexport const getDelayColor = (delayInMs, cancelled, isDelayText) => {\n if (cancelled) {\n return isDelayText ? '#ff0000' : '#a0a0a0'; // red or gray\n }\n if (delayInMs >= 3600000) {\n return '#ed004c'; // pink { r: 237, g: 0, b: 76, s: '237,0,76' };\n }\n if (delayInMs >= 500000) {\n return '#e80000'; // red { r: 232, g: 0, b: 0, s: '232,0,0' };\n }\n if (delayInMs >= 300000) {\n return '#ff4a00'; // orange { r: 255, g: 74, b: 0, s: '255,74,0' };\n }\n if (delayInMs >= 180000) {\n return '#f7bf00'; // yellow { r: 247, g: 191, b: 0, s: '247,191,0' };\n }\n if (delayInMs === null) {\n return '#a0a0a0'; // grey { r: 160, g: 160, b: 160, s: '160,160,160' };\n }\n return '#00a00c'; // green { r: 0, g: 160, b: 12, s: '0,160,12' };\n};\n\n/**\n * @ignore\n */\nexport const getDelayText = (delayInMs, cancelled) => {\n if (cancelled) {\n return String.fromCodePoint(0x00d7);\n }\n if (delayInMs > 3600000) {\n const rounded = Math.round(delayInMs / 3600000);\n return `+${rounded}h`;\n }\n\n if (delayInMs > 59000) {\n const rounded = Math.round(delayInMs / 60000);\n return `+${rounded}m`;\n }\n\n if (delayInMs > 0) {\n return `+${delayInMs}s`;\n }\n\n return '';\n};\n","import {\n getRadius,\n getBgColor,\n getDelayColor,\n getDelayText,\n getTextColor,\n getTextSize,\n} from '../trackerConfig';\n\nconst createCanvas = (width, height) => {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n};\n\n// Draw circle delay background\nconst cacheDelayBg = {};\nexport const getDelayBgCanvas = (origin, radius, color) => {\n const key = `${origin}, ${radius}, ${color}`;\n if (!cacheDelayBg[key]) {\n const canvas = createCanvas(origin * 2, origin * 2);\n const ctx = canvas.getContext('2d');\n ctx.beginPath();\n ctx.arc(origin, origin, radius, 0, 2 * Math.PI, false);\n ctx.fillStyle = color;\n ctx.filter = 'blur(1px)';\n ctx.fill();\n cacheDelayBg[key] = canvas;\n }\n return cacheDelayBg[key];\n};\n\n// Draw delay text\nconst cacheDelayText = {};\nexport const getDelayTextCanvas = (\n width,\n text,\n fontSize,\n font,\n delayColor,\n delayOutlineColor,\n pixelRatio,\n) => {\n const key = `${width}, ${text}, ${font}, ${delayColor}, ${delayOutlineColor}, ${pixelRatio}`;\n if (!cacheDelayText[key]) {\n const canvas = createCanvas(width, fontSize + 8 * pixelRatio);\n const ctx = canvas.getContext('2d');\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.font = font;\n ctx.fillStyle = delayColor;\n ctx.strokeStyle = delayOutlineColor;\n ctx.lineWidth = 1.5 * pixelRatio;\n const delayText = text;\n ctx.strokeText(delayText, 0, fontSize);\n ctx.fillText(delayText, 0, fontSize);\n cacheDelayText[key] = canvas;\n }\n return cacheDelayText[key];\n};\n\n// Draw colored circle with black border\nconst cacheCircle = {};\nexport const getCircleCanvas = (\n origin,\n radius,\n color,\n hasStroke,\n hasDash,\n pixelRatio,\n) => {\n const key = `${origin}, ${radius}, ${color}, ${hasStroke}, ${hasDash}, ${pixelRatio}`;\n if (!cacheCircle[key]) {\n const canvas = createCanvas(origin * 2, origin * 2);\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = color;\n\n if (hasStroke) {\n ctx.lineWidth = 1 * pixelRatio;\n ctx.strokeStyle = '#000000';\n }\n\n ctx.beginPath();\n ctx.arc(origin, origin, radius, 0, 2 * Math.PI, false);\n ctx.fill();\n\n if (hasDash) {\n ctx.setLineDash([5, 3]);\n }\n\n if (hasStroke) {\n ctx.stroke();\n }\n\n cacheCircle[key] = canvas;\n }\n return cacheCircle[key];\n};\n\n// Draw text in the circle\nconst cacheText = {};\nexport const getTextCanvas = (\n text,\n origin,\n textSize,\n fillColor,\n strokeColor,\n hasStroke,\n pixelRatio,\n) => {\n const key = `${text}, ${origin}, ${textSize}, ${fillColor},${strokeColor}, ${hasStroke}, ${pixelRatio}`;\n if (!cacheText[key]) {\n const canvas = createCanvas(origin * 2, origin * 2);\n const ctx = canvas.getContext('2d');\n\n // Draw a stroke to the text only if a provider provides realtime but we don't use it.\n if (hasStroke) {\n ctx.save();\n ctx.textBaseline = 'middle';\n ctx.textAlign = 'center';\n ctx.font = `bold ${textSize + 2}px Arial`;\n ctx.strokeStyle = strokeColor;\n ctx.strokeText(text, origin, origin);\n ctx.restore();\n }\n\n // Draw a text\n ctx.textBaseline = 'middle';\n ctx.textAlign = 'center';\n ctx.fillStyle = fillColor;\n ctx.font = `bold ${textSize}px Arial`;\n ctx.strokeStyle = strokeColor;\n ctx.strokeText(text, origin, origin);\n ctx.fillText(text, origin, origin);\n\n cacheText[key] = canvas;\n }\n return cacheText[key];\n};\n\n/**\n * A tracker style that take in account the delay.\n *\n * @param {*} trajectory The trajectory to render.\n * @param {*} viewState The view state of the map.\n * @param {*} options Some options to change the rendering\n * @return a canvas\n */\nconst styleCache = {};\nconst style = (trajectory, viewState, options) => {\n const {\n hoverVehicleId,\n selectedVehicleId,\n useDelayStyle,\n delayOutlineColor,\n delayDisplay,\n } = options;\n\n const { zoom, pixelRatio } = viewState;\n let { line, type } = trajectory.properties;\n const {\n train_id: id,\n delay,\n cancelled = false,\n operator_provides_realtime_journey: operatorProvidesRealtime,\n } = trajectory.properties;\n\n if (!type) {\n type = 'Rail';\n }\n\n if (!line) {\n line = {};\n }\n\n let { name, text_color: textColor, color } = line;\n\n if (!name) {\n name = 'I';\n }\n\n if (!textColor) {\n textColor = '#000000';\n }\n\n if (color && color[0] !== '#') {\n color = `#${color}`;\n }\n\n if (textColor[0] !== '#') {\n textColor = `#${textColor}`;\n }\n\n const z = Math.min(Math.floor(zoom || 1), 16);\n const hover = hoverVehicleId && hoverVehicleId === id;\n const selected = selectedVehicleId && selectedVehicleId === id;\n\n // Calcul the radius of the circle\n let radius = getRadius(type, z) * pixelRatio;\n const isDisplayStrokeAndDelay = radius >= 7 * pixelRatio;\n if (hover || selected) {\n radius = isDisplayStrokeAndDelay\n ? radius + 5 * pixelRatio\n : 14 * pixelRatio;\n }\n const mustDrawText = radius > 10 * pixelRatio;\n\n // Optimize the cache key, very important in high zoom level\n let key = `${radius}${type}${color}${hover}${selected}${cancelled}${delay}`;\n\n if (useDelayStyle) {\n key += `${operatorProvidesRealtime}`;\n }\n\n if (mustDrawText) {\n key += `${name}${textColor}`;\n }\n\n if (!styleCache[key]) {\n if (radius === 0) {\n styleCache[key] = null;\n return null;\n }\n\n const margin = 1 * pixelRatio;\n const radiusDelay = radius + 2;\n const markerSize = radius * 2;\n const size = radiusDelay * 2 + margin * 2 + 100 * pixelRatio; // add space for delay information\n const origin = size / 2;\n\n // Create the canvas\n const canvas = createCanvas(size, size);\n const ctx = canvas.getContext('2d');\n\n if (isDisplayStrokeAndDelay && delay !== null) {\n // Draw circle delay background\n const delayBg = getDelayBgCanvas(\n origin,\n radiusDelay,\n getDelayColor(delay, cancelled),\n );\n ctx.drawImage(delayBg, 0, 0);\n }\n\n // Show delay if feature is hovered or if delay is above 5mins.\n if (\n isDisplayStrokeAndDelay &&\n (hover || delay >= delayDisplay || cancelled)\n ) {\n // Draw delay text\n const fontSize =\n Math.max(\n cancelled ? 19 : 14,\n Math.min(cancelled ? 19 : 17, radius * 1.2),\n ) * pixelRatio;\n const text = getDelayText(delay, cancelled);\n\n if (text) {\n const textWidth = text.length * fontSize;\n const delayText = getDelayTextCanvas(\n textWidth,\n text,\n fontSize,\n `bold ${fontSize}px arial, sans-serif`,\n getDelayColor(delay, cancelled, true),\n delayOutlineColor,\n pixelRatio,\n );\n ctx.drawImage(\n delayText,\n origin + radiusDelay + margin,\n origin - fontSize,\n );\n }\n }\n\n // Draw colored circle with black border\n let circleFillColor;\n if (useDelayStyle) {\n circleFillColor = getDelayColor(delay, cancelled);\n } else {\n circleFillColor = color || getBgColor(type);\n }\n\n const hasStroke = isDisplayStrokeAndDelay || hover || selected;\n\n const hasDash =\n isDisplayStrokeAndDelay &&\n useDelayStyle &&\n delay === null &&\n operatorProvidesRealtime === 'yes';\n\n const circle = getCircleCanvas(\n origin,\n radius,\n circleFillColor,\n hasStroke,\n hasDash,\n pixelRatio,\n );\n\n ctx.drawImage(circle, 0, 0);\n\n // Draw text in the circle\n if (mustDrawText) {\n const fontSize = Math.max(radius, 10);\n const textSize = getTextSize(ctx, markerSize, name, fontSize);\n const textColor2 = !useDelayStyle\n ? textColor || getTextColor(type)\n : '#000000';\n const hasStroke2 =\n useDelayStyle && delay === null && operatorProvidesRealtime === 'yes';\n\n const text = getTextCanvas(\n name,\n origin,\n textSize,\n textColor2,\n circleFillColor,\n hasStroke2,\n pixelRatio,\n );\n\n ctx.drawImage(text, 0, 0);\n }\n\n styleCache[key] = canvas;\n }\n\n return styleCache[key];\n};\nexport default style;\n","/* eslint-disable no-underscore-dangle */\nimport { toLonLat } from 'ol/proj';\nimport { Map } from 'mapbox-gl';\nimport Source from 'ol/source/Source';\nimport OLLayer from 'ol/layer/Layer';\nimport GeoJSON from 'ol/format/GeoJSON';\nimport Layer from './Layer';\nimport { getMapboxMapCopyrights, getMapboxStyleUrl } from '../../common/utils';\n\n/**\n * A class representing Mapboxlayer to display on BasicMap\n *\n * @example\n * import { MapboxLayer } from 'mobility-toolbox-js/ol';\n *\n * const layer = new MapboxLayer({\n * url: 'https://maps.geops.io/styles/travic_v2/style.json',\n * apikey: 'yourApiKey',\n * });\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nexport default class MapboxLayer extends Layer {\n /**\n * Constructor.\n *\n * @param {Object} options\n * @param {boolean} [options.preserveDrawingBuffer=false] If true able to export the canvas.\n * @param {number} [options.fadeDuration=300] Duration of the fade effect in ms.\n */\n constructor(options = {}) {\n const mbLayer = new OLLayer({\n source: new Source({}),\n render: (frameState) => {\n if (!this.mbMap) {\n // eslint-disable-next-line no-console\n console.warn(\"Mapbox map doesn't exist.\");\n return null;\n }\n let changed = false;\n const canvas = this.mbMap.getCanvas();\n const { viewState } = frameState;\n\n const visible = this.olLayer.getVisible();\n if (this.renderState.visible !== visible) {\n canvas.style.display = visible ? 'block' : 'none';\n this.renderState.visible = visible;\n // Needed since mapbox-gl 1.9.0.\n // Without you don't see others ol layers on top.\n canvas.style.position = 'absolute';\n }\n\n const opacity = this.olLayer.getOpacity();\n if (this.renderState.opacity !== opacity) {\n canvas.style.opacity = opacity;\n this.renderState.opacity = opacity;\n }\n\n // adjust view parameters in mapbox\n const { rotation } = viewState;\n if (this.renderState.rotation !== rotation) {\n this.mbMap.rotateTo((-(rotation || 0) * 180) / Math.PI, {\n animate: false,\n });\n changed = true;\n this.renderState.rotation = rotation;\n }\n\n if (\n this.renderState.zoom !== viewState.zoom ||\n this.renderState.center[0] !== viewState.center[0] ||\n this.renderState.center[1] !== viewState.center[1]\n ) {\n this.mbMap.jumpTo({\n center: toLonLat(viewState.center),\n zoom: viewState.zoom - 1,\n animate: false,\n });\n changed = true;\n this.renderState.zoom = viewState.zoom;\n this.renderState.center = viewState.center;\n }\n\n const size = this.map.getSize();\n if (\n this.renderState.size[0] !== size[0] ||\n this.renderState.size[1] !== size[1]\n ) {\n changed = true;\n this.renderState.size = size;\n }\n\n // cancel the scheduled update & trigger synchronous redraw\n // see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184\n // NOTE: THIS MIGHT BREAK WHEN UPDATING MAPBOX\n if (\n this.mbMap &&\n this.mbMap.style &&\n this.mbMap.isStyleLoaded() &&\n changed\n ) {\n try {\n if (this.mbMap._frame) {\n this.mbMap._frame.cancel();\n this.mbMap._frame = null;\n }\n this.mbMap._render();\n } catch (err) {\n // ignore render errors because it's probably related to\n // a render during an update of the style.\n // eslint-disable-next-line no-console\n console.warn(err);\n }\n }\n\n return this.mbMap.getContainer();\n },\n });\n\n super({\n ...options,\n olLayer: mbLayer,\n });\n\n /**\n * Url of the mapbox style.\n * @type {string}\n * @private\n */\n this.styleUrl = options.url;\n\n /**\n * Api key for the url of the mapbox style.\n * If set to false, the apiKey is not required.\n * @type {string}\n * @private\n */\n this.apiKey = options.apiKey;\n\n /**\n * Name of the apiKey to set in the url request.\n * Default is 'key'.\n * @type {string}\n * @private\n */\n this.apiKeyName = options.apiKeyName || 'key';\n\n /** @ignore */\n this.updateAttribution = this.updateAttribution.bind(this);\n }\n\n /**\n * Initialize the layer and listen to feature clicks.\n * @param {ol/Map~Map} map\n */\n init(map) {\n super.init(map);\n\n if (!this.map || this.mbMap) {\n return;\n }\n\n /**\n * The feature format.\n * @type {ol/format/GeoJSON}\n */\n this.format = new GeoJSON({\n featureProjection: this.map.getView().getProjection(),\n });\n\n this.loadMbMap();\n\n this.olListenersKeys.push(\n this.map.on('change:size', () => {\n try {\n if (this.mbMap) {\n this.mbMap.resize();\n }\n } catch (err) {\n // ignore render errors\n // eslint-disable-next-line no-console\n console.warn(err);\n }\n }),\n );\n }\n\n /**\n * Terminate what was initialized in init function. Remove layer, events...\n */\n terminate() {\n if (this.mbMap) {\n this.mbMap.off('idle', this.updateAttribution);\n // Some asynchrone repaints are triggered even if the mbMap has been removed,\n // to avoid display of errors we set an empty function.\n this.mbMap.triggerRepaint = () => {};\n this.mbMap.remove();\n this.mbMap = null;\n }\n this.loaded = false;\n super.terminate();\n }\n\n /**\n * Returns a style URL with apiKey & apiKeyName infos.\n * @private\n */\n createStyleUrl() {\n return getMapboxStyleUrl(this.apiKey, this.apiKeyName, this.styleUrl);\n }\n\n /**\n * Create the mapbox map.\n * @private\n */\n loadMbMap() {\n this.olListenersKeys.push(\n this.map.on('change:target', () => {\n this.loadMbMap();\n }),\n );\n\n if (!this.map.getTargetElement()) {\n return;\n }\n\n if (!this.visible) {\n // On next change of visibility we load the map\n this.olListenersKeys.push(\n this.once('change:visible', () => {\n this.loadMbMap();\n }),\n );\n return;\n }\n\n // If the map hasn't been resized, the center could be [NaN,NaN].\n // We set default good value for the mapbox map, to avoid the app crashes.\n let [x, y] = this.map.getView().getCenter();\n if (!x || !y) {\n x = 0;\n y = 0;\n }\n\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.width = '100%';\n container.style.height = '100%';\n\n /**\n * A mapbox map\n * @type {mapboxgl.Map}\n */\n this.mbMap = new Map({\n style: this.createStyleUrl(),\n container,\n interactive: false,\n trackResize: false,\n attributionControl: false,\n ...(this.options.mapOptions || {}),\n });\n\n // Options the last render run did happen. If something changes\n // we have to render again\n /** @ignore */\n this.renderState = {\n center: [x, y],\n zoom: null,\n rotation: null,\n visible: null,\n opacity: null,\n size: [0, 0],\n };\n\n this.mbMap.once('load', () => {\n this.mbMap.resize();\n /**\n * Is the map loaded.\n * @type {boolean}\n */\n this.loaded = true;\n\n /** @ignore */\n this.copyrights = getMapboxMapCopyrights(this.mbMap) || [];\n\n this.olLayer.getSource().setAttributions(this.copyrights);\n\n this.dispatchEvent({\n type: 'load',\n target: this,\n });\n });\n\n const mapboxCanvas = this.mbMap.getCanvas();\n if (mapboxCanvas) {\n if (this.options.tabIndex) {\n mapboxCanvas.setAttribute('tabindex', this.options.tabIndex);\n } else {\n // With a tabIndex='-1' the mouse events works but the map is not focused when we click on it\n // so we remove completely the tabIndex attribute.\n mapboxCanvas.removeAttribute('tabindex');\n }\n }\n\n this.mbMap.on('idle', this.updateAttribution);\n }\n\n /**\n * Update attributions of the source.\n * @private\n */\n updateAttribution(evt) {\n const newAttributions = getMapboxMapCopyrights(evt.target) || [];\n if (this.copyrights.toString() !== newAttributions.toString()) {\n this.copyrights = newAttributions;\n this.olLayer.getSource().setAttributions(newAttributions);\n }\n }\n\n /**\n * Request feature information for a given coordinate.\n * @param {ol/coordinate~Coordinate} coordinate Coordinate to request the information at.\n * @param {Object} options A [mapboxgl.Map#queryrenderedfeatures](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures) options parameter.\n * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate. The original Mapbox feature is available as a property named 'mapboxFeature'.\n */\n getFeatureInfoAtCoordinate(coordinate, options) {\n // Ignore the getFeatureInfo until the mapbox map is loaded\n if (\n !options ||\n !this.format ||\n !this.mbMap ||\n !this.mbMap.isStyleLoaded()\n ) {\n return Promise.resolve({ coordinate, features: [], layer: this });\n }\n\n let pixel = coordinate && this.mbMap.project(toLonLat(coordinate));\n\n if (this.hitTolerance) {\n const { x, y } = pixel;\n pixel = [\n { x: x - this.hitTolerance, y: y - this.hitTolerance },\n { x: x + this.hitTolerance, y: y + this.hitTolerance },\n ];\n }\n\n // At this point we get GeoJSON Mapbox feature, we transform it to an OpenLayers\n // feature to be consistent with other layers.\n const features = this.mbMap\n .queryRenderedFeatures(pixel, options)\n .map((feature) => {\n const olFeature = this.format.readFeature(feature);\n if (olFeature) {\n // We save the original mapbox feature to avoid losing informations\n // potentially needed for other functionnality like highlighting\n // (id, layer id, source, sourceLayer ...)\n olFeature.set('mapboxFeature', feature);\n }\n return olFeature;\n });\n\n return Promise.resolve({\n layer: this,\n features,\n coordinate,\n });\n }\n\n /**\n * Create a copy of the MapboxLayer.\n * @param {Object} newOptions Options to override\n * @return {MapboxLayer} A MapboxLayer\n */\n clone(newOptions) {\n return new MapboxLayer({ ...this.options, ...newOptions });\n }\n}\n","import { Circle, Fill, Stroke, Style } from 'ol/style';\nimport { Vector as VectorSource } from 'ol/source';\nimport { Vector } from 'ol/layer';\nimport Layer from './Layer';\n\nconst circleStyle = new Circle({\n radius: 6,\n fill: new Fill({\n color: [255, 0, 0, 1],\n }),\n stroke: new Stroke({\n color: [0, 0, 0, 1],\n width: 1,\n }),\n});\n\nconst blackBorder = new Style({\n stroke: new Stroke({\n color: [0, 0, 0, 1],\n width: 5,\n }),\n});\n\nconst redLine = new Style({\n image: circleStyle,\n stroke: new Stroke({\n color: [255, 0, 0, 1],\n width: 3,\n }),\n});\n\nconst dashedRedLine = new Style({\n image: circleStyle,\n stroke: new Stroke({\n color: [255, 0, 0, 1],\n width: 3,\n lineDash: [1, 10],\n }),\n});\n\nconst defaultStyleFunction = (feature, resolution) => {\n const minResolution = feature.get('minResolution');\n const maxResolution = feature.get('maxResolution');\n const inRange = resolution <= minResolution && resolution > maxResolution;\n\n if (minResolution && maxResolution && !inRange) {\n return null;\n }\n const mot = feature.get('mot');\n\n if (mot !== 'foot') {\n return [blackBorder, redLine];\n }\n\n return [dashedRedLine];\n};\n\n/**\n * A class use to display vector data.\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass RoutingLayer extends Layer {\n /**\n * Constructor.\n * @param {Object} [options]\n * @param {ol/style/Style~StyleLike} [options.style] Style to be used for routes, uses (ol/StyleLike) [https://openlayers.org/en/latest/apidoc/module-ol_style_Style.html#~StyleLike] instances\n */\n constructor(options = {}) {\n super(options);\n\n this.olLayer =\n options.olLayer ||\n new Vector({\n source: new VectorSource(),\n style: options.style || defaultStyleFunction,\n });\n }\n\n /**\n * Create a copy of the RoutingLayer.\n * @param {Object} newOptions Options to override\n * @return {RoutingLayer} A RoutingLayer\n */\n clone(newOptions) {\n return new RoutingLayer({ ...this.options, ...newOptions });\n }\n}\n\nexport default RoutingLayer;\n","import GeomType from 'ol/geom/GeometryType';\n\n/**\n * Interpolate or not the vehicle position from a trajectory at a specific date.\n *\n * @param {number} now Current date to interpolate a position with. In ms.\n * @param {TralisTrajectory} trajectory The trajectory to interpolate.\n * @param {boolean} noInterpolate If true, the vehicle position is not interpolated on each render but only once.\n * @returns\n */\nconst getVehiclePosition = (now, trajectory, noInterpolate) => {\n const {\n time_intervals: timeIntervals,\n olGeometry: geometry,\n coordinate,\n } = trajectory.properties;\n\n let coord;\n let rotation;\n\n if (noInterpolate && coordinate) {\n coord = coordinate;\n } else if (geometry.getType() === GeomType.POINT) {\n coord = geometry.getCoordinates();\n } else if (geometry.getType() === GeomType.LINE_STRING) {\n const intervals = timeIntervals || [[]];\n const firstInterval = intervals[0];\n const lastInterval = intervals[intervals.length - 1];\n\n // Between the last time interval of a trajectory event and the beginning\n // of the new trajectory event, there is few seconds, can be 6 to 30\n // seconds (that's why the vehicle jumps sometimes).\n // So we make the choice here to display the last (or the first) position\n // of an trajectory event instead of removing them, if the current date is\n // outside the time intervals we display the vehicle at the last (or first) position known.\n if (now < firstInterval[0]) {\n // Display first position known.\n [, , rotation] = firstInterval;\n coord = geometry.getFirstCoordinate();\n } else if (now > lastInterval[0]) {\n // Display last position known.\n [, , rotation] = lastInterval;\n coord = geometry.getLastCoordinate();\n } else {\n // Interpolate position using time intervals.\n for (let j = 0; j < intervals.length - 1; j += 1) {\n // Rotation only available in tralis layer.\n const [start, startFrac] = intervals[j];\n const [end, endFrac] = intervals[j + 1];\n\n if (start <= now && now <= end) {\n // interpolate position inside the time interval.\n const timeFrac = Math.min((now - start) / (end - start), 1);\n const geomFrac = timeFrac * (endFrac - startFrac) + startFrac;\n coord = geometry.getCoordinateAt(geomFrac);\n [, , rotation] = intervals[j];\n break;\n }\n }\n }\n } else {\n // eslint-disable-next-line no-console\n console.error(\n 'This geometry type is not supported. Only Point or LineString are. Current geometry: ',\n geometry,\n );\n }\n\n return { coord, rotation };\n};\n\nexport default getVehiclePosition;\n","/* eslint-disable no-param-reassign */\nimport { compose, apply, create } from 'ol/transform';\nimport getVehiclePosition from './utils/getVehiclePosition';\n\n/**\n * Tracker. This class stores and allows to draw trajectories on a canvas.\n * @class\n * @param {Object} options\n * @private\n */\nexport default class Tracker {\n /**\n * @private\n */\n constructor(options) {\n /**\n * Function use to style the features displayed.\n * @type {function}\n */\n this.style = options.style;\n\n // we draw directly on the canvas since openlayers is too slow.\n /**\n * HTML <canvas> element.\n * @type {Canvas}\n */\n this.canvas = options.canvas || document.createElement('canvas');\n }\n\n /**\n * Draw all the trajectories available to the canvas.\n * @param {ViewState} trajectories An array of trajectories.\n * @param {ViewState} viewState The view state of the map.\n * @param {boolean} options.hoverVehicleId The id of the vehicle to highlight.\n * @param {boolean} options.selectedVehicleId The id of the vehicle to select.\n * @param {boolean} options.noInterpolate If true trajectories are not interpolated but\n * drawn at the last known coordinate. Use this for performance optimization\n * during map navigation.\n * @private\n */\n renderTrajectories(trajectories, viewState, options) {\n const {\n time = Date.now(),\n size = [],\n center,\n resolution,\n rotation = 0,\n pixelRatio,\n } = viewState;\n const {\n noInterpolate = false,\n hoverVehicleId,\n selectedVehicleId,\n } = options;\n\n const { canvas } = this;\n const context = canvas.getContext('2d');\n context.clearRect(0, 0, canvas.width, canvas.height);\n\n const [width, height] = size;\n if (\n width &&\n height &&\n (canvas.width !== width || canvas.height !== height)\n ) {\n [canvas.width, canvas.height] = [width * pixelRatio, height * pixelRatio];\n }\n\n const coordinateToPixelTransform = compose(\n create(),\n size[0] / 2,\n size[1] / 2,\n 1 / resolution,\n -1 / resolution,\n -rotation,\n -center[0],\n -center[1],\n );\n\n // Offscreen canvas has not style attribute\n if (canvas.style) {\n canvas.style.width = `${canvas.width / pixelRatio}px`;\n canvas.style.height = `${canvas.height / pixelRatio}px`;\n }\n\n let hoverVehicleImg;\n let hoverVehiclePx;\n let hoverVehicleWidth;\n let hoverVehicleHeight;\n let selectedVehicleImg;\n let selectedVehiclePx;\n let selectedVehicleWidth;\n let selectedVehicleHeight;\n let nbRendered = 0;\n\n for (let i = trajectories.length - 1; i >= 0; i -= 1) {\n const trajectory = trajectories[i];\n\n // We simplify the trajectory object\n const { train_id: id, timeOffset } = trajectory.properties;\n // We set the rotation and the timeFraction of the trajectory (used by tralis).\n // if rotation === null that seems there is no rotation available.\n const { coord, rotation: rotationIcon } = getVehiclePosition(\n time - (timeOffset || 0),\n trajectory,\n noInterpolate,\n );\n\n // We store the current vehicle position to the trajectory.\n trajectories[i].properties.coordinate = coord;\n trajectories[i].properties.rotation = rotationIcon;\n\n if (!coord) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n let px = apply(coordinateToPixelTransform, [...coord]);\n if (!px) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n px = px.map((p) => p * pixelRatio);\n\n if (\n px[0] < 0 ||\n px[0] > canvas.width ||\n px[1] < 0 ||\n px[1] > canvas.height\n ) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n const vehicleImg = this.style(trajectory, viewState, options);\n if (!vehicleImg) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n nbRendered += 1;\n\n const imgWidth = vehicleImg.width;\n const imgHeight = vehicleImg.height;\n\n if (hoverVehicleId !== id && selectedVehicleId !== id) {\n context.drawImage(\n vehicleImg,\n px[0] - imgWidth / 2,\n px[1] - imgHeight / 2,\n imgWidth,\n imgHeight,\n );\n }\n\n if (hoverVehicleId && hoverVehicleId === id) {\n // Store the canvas to draw it at the end\n hoverVehicleImg = vehicleImg;\n hoverVehiclePx = px;\n hoverVehicleWidth = imgWidth;\n hoverVehicleHeight = imgHeight;\n }\n\n if (selectedVehicleId && selectedVehicleId === id) {\n // Store the canvas to draw it at the end\n selectedVehicleImg = vehicleImg;\n selectedVehiclePx = px;\n selectedVehicleWidth = imgWidth;\n selectedVehicleHeight = imgHeight;\n }\n }\n\n if (selectedVehicleImg) {\n context.drawImage(\n selectedVehicleImg,\n selectedVehiclePx[0] - selectedVehicleWidth / 2,\n selectedVehiclePx[1] - selectedVehicleHeight / 2,\n selectedVehicleWidth,\n selectedVehicleHeight,\n );\n }\n\n if (hoverVehicleImg) {\n context.drawImage(\n hoverVehicleImg,\n hoverVehiclePx[0] - hoverVehicleWidth / 2,\n hoverVehiclePx[1] - hoverVehicleHeight / 2,\n hoverVehicleWidth,\n hoverVehicleHeight,\n );\n }\n return {\n nbTrajectoriesRendered: nbRendered,\n };\n }\n}\n","/**\n * Return a filter functions based on some parameters of a vehicle.\n *\n * @param {string|Array<string>} line - A list of vehicle's name to filter. Names can be separated by a comma. Ex: 'S1,S2,S3'\n * @param {string|Array<string} route - A list of vehicle's route (contained in routeIdentifier property) to filter. Indentifiers can be separated by a comma. Ex: 'id1,id2,id3'\n * @param {string|Array<string} operator A list of vehicle's operator to filter. Operators can be separated by a comma. Ex: 'SBB,DB'\n * @param {Regexp} regexLine - A regex aplly of vehcile's name.\n * @private\n */\nconst createFilters = (line, route, operator, regexLine) => {\n const filterList = [];\n\n if (!line && !route && !operator && !regexLine) {\n return null;\n }\n\n if (regexLine) {\n const regexLineList =\n typeof regexLine === 'string' ? [regexLine] : regexLine;\n const lineFilter = (item) => {\n const name =\n item.properties.name ||\n (item.properties.line && item.properties.line.name) ||\n '';\n if (!name) {\n return false;\n }\n return regexLineList.some((regexStr) =>\n new RegExp(regexStr, 'i').test(name),\n );\n };\n filterList.push(lineFilter);\n }\n\n if (line) {\n const lineFiltersList = typeof line === 'string' ? line.split(',') : line;\n const lineList = lineFiltersList.map((l) =>\n l.replace(/\\s+/g, '').toUpperCase(),\n );\n const lineFilter = (item) => {\n const { line: linee, name } = item.properties;\n const lineName = (name || (linee && linee.name) || '').toUpperCase();\n if (!lineName) {\n return false;\n }\n return lineList.includes(lineName);\n };\n filterList.push(lineFilter);\n }\n\n if (route) {\n const routes = typeof route === 'string' ? route.split(',') : route;\n const routeList = routes.map((item) => parseInt(item, 10));\n const routeFilter = (item) => {\n const routeId = parseInt(\n item.properties.routeIdentifier.split('.')[0],\n 10,\n );\n return routeList.includes(routeId);\n };\n filterList.push(routeFilter);\n }\n\n if (operator) {\n const operatorList = typeof operator === 'string' ? [operator] : operator;\n const operatorFilter = (item) =>\n operatorList.some((op) =>\n new RegExp(op, 'i').test(item.properties.operator),\n );\n filterList.push(operatorFilter);\n }\n\n if (!filterList.length) {\n return null;\n }\n\n return (t) => {\n for (let i = 0; i < filterList.length; i += 1) {\n if (!filterList[i](t)) {\n return false;\n }\n }\n return true;\n };\n};\n\nexport default createFilters;\n","import qs from 'query-string';\nimport BaseObject from 'ol/Object';\n\n/**\n * Common class to access to a geOps api.\n *\n * @example\n * import { API } from 'mobility-toolbox-js/api';\n *\n * const api = new API({\n * url: [yourUrl],\n * apiKey: [yourApiKey]\n * });\n *\n * @classproperty {string} url Url of the service.\n * @classproperty {string} apiKey Api key to access the service.\n */\nclass API extends BaseObject {\n constructor(options = {}) {\n super();\n /** @ignore */\n this.url = options.url;\n\n /** @ignore */\n this.apiKey = options.apiKey;\n }\n\n /**\n * Append the apiKey before sending the request.\n * @ignore\n */\n fetch(path, params, config) {\n // Clean requets parameters, removing undefined and null values.\n const urlParams = { ...(params || {}), key: this.apiKey };\n const clone = { ...urlParams };\n Object.keys(urlParams).forEach(\n (key) =>\n (clone[key] === undefined || clone[key] === null) && delete clone[key],\n );\n if (!this.apiKey) {\n // eslint-disable-next-line no-console\n return Promise.reject(\n new Error(`No apiKey defined for request to ${this.url}`),\n );\n }\n return fetch(\n `${this.url}${path || ''}?${qs.stringify(clone)}`,\n config,\n ).then((response) => {\n try {\n return response.json().then((data) => {\n if (data.error) {\n throw new Error(data.error);\n }\n return data;\n });\n } catch (err) {\n return Promise.reject(new Error(err));\n }\n });\n }\n}\n\nexport default API;\n","import API from '../../common/api/api';\n\n/**\n * Access to the [Stops service](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).\n *\n * @example\n * import { StopsAPI } from 'mobility-toolbox-js/api';\n *\n * const api = new StopsAPI({\n * url: 'https://api.geops.io/stops/v1/',\n * apiKey: [yourApiKey]\n * });\n *\n */\nclass StopsAPI extends API {\n /**\n * Constructor\n *\n * @param {Object} options Options.\n * @param {string} [options.url='https://api.geops.io/stops/v1/'] Service url.\n * @param {string} options.apiKey Access key for [geOps services](https://developer.geops.io/).\n */\n constructor(options = {}) {\n super({ url: 'https://api.geops.io/stops/v1/', ...options });\n }\n\n /**\n * Search.\n *\n * @param {StopsSearchParams} params Request parameters. See [Stops service documentation](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).\n * @param {AbortController} abortController Abort controller used to cancel the request.\n * @return {Promise<Array<GeoJSONFeature>>} An array of GeoJSON features with coordinates in [EPSG:4326](http://epsg.io/4326).\n */\n search(params, abortController = {}) {\n return this.fetch('', params, {\n signal: abortController.signal,\n }).then((featureCollection) => featureCollection.features);\n }\n}\n\nexport default StopsAPI;\n","/**\n * Class used to facilitate connection to a WebSocket and\n * also to manage properly messages send to the WebSocket.\n * This class must not contain any specific implementation.\n *\n * @private\n */\nclass WebSocketConnector {\n constructor() {\n this.defineProperties();\n }\n\n defineProperties() {\n Object.defineProperties(this, {\n closed: {\n get: () =>\n !!(\n this.websocket &&\n this.websocket.readyState === this.websocket.CLOSED\n ),\n },\n closing: {\n get: () =>\n !!(\n this.websocket &&\n this.websocket.readyState === this.websocket.CLOSING\n ),\n },\n connecting: {\n get: () =>\n !!(\n this.websocket &&\n this.websocket.readyState === this.websocket.CONNECTING\n ),\n },\n open: {\n get: () =>\n !!(\n this.websocket && this.websocket.readyState === this.websocket.OPEN\n ),\n },\n /**\n * Array of message to send on open.\n * @type {Array<string>}\n * @private\n */\n messagesOnOpen: {\n value: [],\n writable: true,\n },\n /**\n * Array of subscriptions.\n * @type {Array<subscription>}\n * @private\n */\n subscriptions: {\n value: [],\n writable: true,\n },\n\n /**\n * List of channels subscribed.\n * @type {Array<subscription>}\n * @private\n */\n subscribed: {\n value: {},\n writable: true,\n },\n });\n }\n\n /**\n * Get the websocket request string.\n *\n * @param {string} method Request mehtod {GET, SUB}.\n * @param {Object} params Request parameters.\n * @param {string} params.channel Channel name\n * @param {string} [params.args] Request arguments\n * @param {Number} [params.id] Request identifier\n * @return {string} request string\n * @private\n */\n static getRequestString(method, params) {\n let reqStr = `${method} ${params.channel}`;\n reqStr += params.args ? ` ${params.args}` : '';\n reqStr += params.id ? ` ${params.id}` : '';\n return reqStr.trim();\n }\n\n /**\n * (Re)connect the websocket.\n *\n * @param {strin} url Websocket url.\n * @param {function} onOpen Callback called when the websocket connection is opened and before subscriptions of previous subscriptions.\n * @private\n */\n connect(url, onOpen = () => {}) {\n if (this.websocket && !this.closed) {\n this.websocket.close();\n }\n\n /** @ignore */\n this.websocket = new WebSocket(url);\n\n if (!this.open) {\n this.websocket.addEventListener('open', () => {\n onOpen();\n this.subscribePreviousSubscriptions();\n });\n } else {\n onOpen();\n this.subscribePreviousSubscriptions();\n }\n }\n\n /**\n * Close the websocket definitively.\n *\n * @private\n */\n close() {\n if (this.websocket) {\n this.websocket.onclose = null;\n this.websocket.close();\n this.websocket = null;\n this.messagesOnOpen = [];\n }\n }\n\n /**\n * Sends a message to the websocket.\n *\n * @param {message} message Message to send.\n * @private\n */\n send(message) {\n if (!this.websocket) {\n return;\n }\n const send = () => {\n this.websocket.send(message);\n };\n if (!this.open) {\n // This 'if' avoid sending 2 identical BBOX message on open,\n if (!this.messagesOnOpen.includes(message)) {\n this.messagesOnOpen.push(message);\n this.websocket.addEventListener('open', () => {\n this.messagesOnOpen = [];\n send();\n });\n this.websocket.addEventListener('close', () => {\n this.messagesOnOpen = [];\n });\n }\n } else if (!this.messagesOnOpen.includes(message)) {\n send();\n }\n }\n\n /**\n * Listen to websocket messages.\n *\n * @param {Object} params Parameters for the websocket get request\n * @param {function} cb callback on listen\n * @param {function} errorCb Callback on error\n * @return {{onMessage: function, errorCb: function}} Object with onMessage and error callbacks\n * @private\n */\n listen(params, cb, errorCb) {\n // Remove the previous identical callback\n this.unlisten(params, cb);\n\n const onMessage = (evt) => {\n let data = {};\n try {\n data = JSON.parse(evt.data);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('WebSocket: unable to parse JSON data', err, evt.data);\n }\n let source = params.channel;\n source += params.args ? ` ${params.args}` : '';\n\n // Buffer channel message return a list of other channels to propagate to proper callbacks.\n const contents = data.source === 'buffer' ? data.content : [data];\n contents.forEach((content) => {\n // Because of backend optimization, the last content is null.\n if (\n content?.source === source &&\n (!params.id || params.id === data.client_reference)\n ) {\n cb(content);\n }\n });\n };\n\n if (this.websocket) {\n this.websocket.addEventListener('message', onMessage);\n\n if (errorCb) {\n this.websocket.addEventListener('error', errorCb);\n this.websocket.addEventListener('close', errorCb);\n }\n }\n\n return { onMessageCb: onMessage, onErrorCb: errorCb };\n }\n\n /**\n * Unlisten websocket messages.\n *\n * @param {Object} params Parameters for the websocket get request.\n * @param {function} cb Callback used when listen.\n * @private\n */\n unlisten(params, cb) {\n if (!this.websocket) {\n return;\n }\n this.subscriptions\n .filter(\n (s) => s.params.channel === params.channel && (!cb || s.cb === cb),\n )\n .forEach(({ onMessageCb, onErrorCb }) => {\n if (this.websocket) {\n this.websocket.removeEventListener('message', onMessageCb);\n if (onErrorCb) {\n this.websocket.removeEventListener('error', onErrorCb);\n this.websocket.removeEventListener('close', onErrorCb);\n }\n }\n });\n }\n\n /**\n * Sends a get request to the websocket.\n *\n * @param {Object} params Parameters for the websocket get request\n * @param {function} cb callback on listen\n * @param {function} errorCb Callback on error\n * @private\n */\n get(params, cb, errorCb) {\n const reqStr = WebSocketConnector.getRequestString('GET', params);\n this.send(reqStr);\n this.listen(params, cb, errorCb);\n }\n\n /**\n * Subscribe to a given channel.\n *\n * @param {Object} params Parameters for the websocket get request\n * @param {function} cb callback on listen\n * @param {function} errorCb Callback on error\n * @param {boolean} quiet if false, no GET or SUB requests are send, only the callback is registered.\n * @private\n */\n subscribe(params, cb, errorCb, quiet = false) {\n const { onMessageCb, onErrorCb } = this.listen(params, cb, errorCb);\n const reqStr = WebSocketConnector.getRequestString('', params);\n\n const index = this.subscriptions.findIndex(\n (subcr) => params.channel === subcr.params.channel && cb === subcr.cb,\n );\n const newSubscr = { params, cb, errorCb, onMessageCb, onErrorCb, quiet };\n if (index > -1) {\n this.subscriptions[index] = newSubscr;\n } else {\n this.subscriptions.push(newSubscr);\n }\n\n if (!this.subscribed[reqStr]) {\n if (!newSubscr.quiet) {\n this.send(`GET ${reqStr}`);\n this.send(`SUB ${reqStr}`);\n }\n this.subscribed[reqStr] = true;\n }\n }\n\n /**\n * Unsubscribe from a channel.\n * @param {string} source source to unsubscribe from\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n * @private\n */\n unsubscribe(source, cb) {\n const toRemove = this.subscriptions.filter(\n (s) => s.params.channel === source && (!cb || s.cb === cb),\n );\n\n toRemove.forEach(({ onMessageCb, onErrorCb }) => {\n if (this.websocket) {\n this.websocket.removeEventListener('message', onMessageCb);\n if (onErrorCb) {\n this.websocket.removeEventListener('error', onErrorCb);\n this.websocket.removeEventListener('close', onErrorCb);\n }\n }\n });\n\n this.subscriptions = this.subscriptions.filter(\n (s) => s.params.channel !== source || (cb && s.cb !== cb),\n );\n\n // If there is no more subscriptions to this channel, and the removed subscriptions didn't register quietly,\n // we DEL it.\n if (\n source &&\n this.subscribed[source] &&\n !this.subscriptions.find((s) => s.params.channel === source) &&\n toRemove.find((subscr) => !subscr.quiet)\n ) {\n this.send(`DEL ${source}`);\n this.subscribed[source] = false;\n }\n }\n\n /**\n * After an auto reconnection we need to re-subscribe to the channels.\n */\n subscribePreviousSubscriptions() {\n // Before to subscribe previous subscriptions we make sure they\n // are all defined as unsubscribed, because this code is asynchrone\n // and a subscription could have been added in between.\n Object.keys(this.subscribed).forEach((key) => {\n this.subscribed[key] = false;\n });\n\n // Subscribe all previous subscriptions.\n [...this.subscriptions].forEach((s) => {\n this.subscribe(s.params, s.cb, s.errorCb, s.quiet);\n });\n }\n}\n\nexport default WebSocketConnector;\n","/**\n * Get the websocket channel suffix, depending on the current mode.\n * @param {String} mode Mode 'topographic' ou 'schematic'.\n * @private\n */\nexport const getModeSuffix = (mode, modes) =>\n mode === modes.SCHEMATIC ? '_schematic' : '';\n\n/**\n * Compare two given departures for sort alogithm,\n * @param {Object} a First departure.\n * @param {Object} b Second departure.\n * @private\n */\nexport const compareDepartures = (a, b, sortByMinArrivalTime = false) => {\n // First LEAVING and HIDDEN, then BOARDING and then sorted by time.\n const topStates = ['HIDDEN', 'LEAVING', 'BOARDING'];\n const aTop = a.has_fzo && topStates.indexOf(a.state) > -1;\n const bTop = b.has_fzo && topStates.indexOf(b.state) > -1;\n\n if (aTop || bTop) {\n if (aTop !== bTop) {\n return aTop ? -1 : 1;\n }\n\n if (a.state !== b.state) {\n // one is leaving\n return topStates.indexOf(a.state) - topStates.indexOf(b.state);\n }\n }\n\n let aDuration = null;\n let bDuration = null;\n const now = Date.now();\n\n if (sortByMinArrivalTime) {\n aDuration = new Date(a.min_arrival_time || a.time).getTime() - now;\n bDuration = new Date(b.min_arrival_time || b.time).getTime() - now;\n } else {\n aDuration = new Date(a.time).getTime() - now;\n bDuration = new Date(b.time).getTime() - now;\n }\n\n return aDuration - bDuration;\n};\n\n/**\n * Remove the delay from arrivalTime and departureTime\n * @private\n */\nexport const cleanStopTime = (content) => {\n if (!content) {\n return;\n }\n content.stations.forEach((station) => {\n // eslint-disable-next-line no-param-reassign\n station.arrivalTimeWithDelay = station.arrivalTime;\n if (station.departureTime) {\n // eslint-disable-next-line no-param-reassign\n station.departureTimeWithDelay = station.departureTime;\n }\n if (station.arrivalDelay) {\n // eslint-disable-next-line no-param-reassign\n station.arrivalTime -= station.arrivalDelay;\n if (station.departureTime) {\n // eslint-disable-next-line no-param-reassign\n station.departureTime -= station.arrivalDelay;\n }\n }\n });\n // eslint-disable-next-line consistent-return\n return content;\n};\n","import WebSocketConnector from './WebSocketConnector';\nimport {\n getModeSuffix,\n cleanStopTime,\n compareDepartures,\n} from './TralisAPIUtils';\n\n/**\n * Enum for Tralis modes.\n * @readonly\n * @typedef {string} TralisMode\n * @property {string} RAW \"raw\"\n * @property {string} SCHEMATIC \"schematic\"\n * @property {string} TOPOGRAPHIC \"topographic\"\n * @enum {TralisMode}\n */\nexport const TralisModes = {\n RAW: 'raw',\n TOPOGRAPHIC: 'topographic',\n SCHEMATIC: 'schematic',\n};\n\n/**\n * This class provides convenience methods to access to the [geOps realtime api](https://developer.geops.io/apis/realtime/).\n *\n * @example\n * import { TralisAPI } from 'mobility-toolbox-js/api';\n *\n * const api = new TralisAPI({\n * url: \"yourUrl\",\n * apiKey: \"yourApiKey\"\n * });\n *\n * @example\n * import { TralisAPI } from 'mobility-toolbox-js/api';\n *\n * const api = new TralisAPI(\"yourUrl\");\n */\nclass TralisAPI {\n /**\n * Constructor\n *\n * @param {Object|string} options A string representing the url of the service or an object containing the url and the apiKey.\n * @param {string} options.url Url to the [geOps realtime api](https://developer.geops.io/apis/realtime/).\n * @param {string} options.apiKey Access key for [geOps apis](https://developer.geops.io/).\n * @param {string} [options.prefix=''] Service prefix to specify tenant.\n * @param {string} [options.projection] The epsg code of the projection for features. Default to EPSG:3857.\n * @param {number[4]} [options.bbox=[minX, minY, maxX, maxY, zoom, tenant] The bounding box to receive data from.\n */\n constructor(options = {}) {\n this.defineProperties(options);\n\n /** @ignore */\n this.subscribedStationUic = null;\n\n /** @ignore */\n this.departureUpdateTimeout = null;\n\n /** @ignore */\n this.maxDepartureAge = 30;\n\n /** @ignore */\n this.extraGeoms = {};\n\n /** @ignore */\n this.prefix = options.prefix || '';\n\n /** @ignore */\n this.onOpen = this.onOpen.bind(this);\n }\n\n defineProperties(options) {\n let opt = options;\n\n if (typeof options === 'string') {\n opt = { url: options };\n }\n\n const { apiKey } = opt;\n let { url, projection, bbox, buffer = [100, 100] } = opt;\n const conn = new WebSocketConnector();\n\n if (apiKey) {\n url = `${url || 'wss://api.geops.io/tracker-ws/v1/'}?key=${apiKey}`;\n }\n\n Object.defineProperties(this, {\n url: {\n get: () => url,\n set: (newUrl) => {\n url = newUrl;\n this.open();\n },\n },\n projection: {\n get: () => projection,\n set: (newProjection) => {\n if (newProjection !== projection) {\n projection = newProjection;\n if (this.conn) {\n this.conn.send(`PROJECTION ${projection}`);\n }\n }\n },\n },\n bbox: {\n get: () => bbox,\n set: (newBbox) => {\n if (JSON.stringify(newBbox) !== JSON.stringify(bbox)) {\n bbox = newBbox;\n if (this.conn) {\n this.conn.send(`BBOX ${bbox.join(' ')}`);\n }\n }\n },\n },\n buffer: {\n get: () => buffer,\n set: (newBuffer) => {\n if (JSON.stringify(newBuffer) !== JSON.stringify(buffer)) {\n buffer = newBuffer;\n if (this.conn) {\n this.conn.send(`BUFFER ${buffer.join(' ')}`);\n }\n }\n },\n },\n /**\n * The websocket helper class to connect the websocket.\n *\n * @private\n */\n conn: {\n value: conn,\n writable: true,\n },\n /**\n * Interval between PING request in ms.\n * If equal to 0, no PING request are sent.\n * @type {number}\n * @private\n */\n pingIntervalMs: {\n value: options.pingIntervalMs || 10000,\n writable: true,\n },\n /**\n * Timeout in ms after an automatic reconnection when the websoscket has been closed by the server.\n * @type {number}\n */\n reconnectTimeoutMs: {\n value: options.pingIntervalMs || 100,\n writable: true,\n },\n });\n }\n\n open() {\n this.close();\n // Register BBOX and PROJECTION messages must be send before previous subscriptions.\n this.conn.connect(this.url, this.onOpen);\n\n // Register reconnection on close.\n this.conn.websocket.onclose = () => {\n this.onClose();\n };\n }\n\n /**\n * Close the websocket connection without reconnection.\n */\n close() {\n this.conn.close();\n }\n\n /**\n * Unsubscribe trajectory and deleted_vehicles channels. To resubscribe you have to set a new BBOX.\n */\n // eslint-disable-next-line class-methods-use-this\n reset() {\n this.conn.send('RESET');\n }\n\n /**\n * Callback when the websocket is opened and ready.\n * It applies the bbox and the projection.\n */\n onOpen() {\n if (this.projection) {\n this.conn.send(`PROJECTION ${this.projection}`);\n }\n\n if (this.bbox) {\n this.conn.send(`BBOX ${this.bbox.join(' ')}`);\n }\n\n if (this.buffer) {\n this.conn.send(`BUFFER ${this.buffer.join(' ')}`);\n }\n\n /**\n * Keep websocket alive\n */\n if (this.pingIntervalMs) {\n window.clearInterval(this.pingInterval);\n /** @ignore */\n this.pingInterval = setInterval(() => {\n this.conn.send('PING');\n }, this.pingIntervalMs);\n }\n }\n\n /**\n * Callback when the websocket is closed by the server.\n * It auto reconnects after a timeout.\n */\n onClose() {\n window.clearTimeout(this.pingInterval);\n window.clearTimeout(this.reconnectTimeout);\n\n if (this.reconnectTimeoutMs) {\n /** @ignore */\n this.reconnectTimeout = window.setTimeout(\n () => this.open(),\n this.reconnectTimeoutMs,\n );\n }\n }\n\n /**\n * Subscribe to a channel.\n *\n * @param {string} channel Name of the websocket channel to subscribe.\n * @param {function} onSuccess Callback when the subscription succeeds.\n * @param {function} onError Callback when the subscription fails.\n * @param {boolean} [quiet=false] If true avoid to store the subscription in the subscriptions list.\n * @private\n */\n subscribe(channel, onSuccess, onError, quiet = false) {\n this.conn.subscribe({ channel }, onSuccess, onError, quiet);\n }\n\n /**\n * Unsubscribe both modes of a channel.\n *\n * @param {string} channel Name of the websocket channel to unsubscribe.\n * @param {string} suffix Suffix to add to the channel name.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n * @private\n */\n unsubscribe(channel, suffix, cb) {\n this.conn.unsubscribe(\n `${channel}${getModeSuffix(TralisModes.SCHEMATIC, TralisModes)}${suffix}`,\n cb,\n );\n this.conn.unsubscribe(\n `${channel}${getModeSuffix(TralisModes.TOPOGRAPHIC, TralisModes)}${\n suffix || ''\n }`,\n cb,\n );\n }\n\n /**\n * Filter departures and return an array.\n *\n * @param {Object} depObject The object containing departures by id.\n * @param {boolean} [sortByMinArrivalTime=false] If true sort departures by arrival time.\n * @return {Array<departure>} Return departures array.\n * @private\n */\n filterDepartures(depObject, sortByMinArrivalTime = false) {\n const departures = Object.keys(depObject).map((k) => depObject[k]);\n departures.sort((a, b) => compareDepartures(a, b, sortByMinArrivalTime));\n\n let future = new Date();\n future.setMinutes(future.getMinutes() + this.maxDepartureAge);\n future = future.getTime();\n\n let past = new Date();\n past.setMinutes(past.getMinutes() - this.maxDepartureAge);\n past = past.getTime();\n\n const departureArray = [];\n const platformsBoarding = [];\n let previousDeparture = null;\n\n for (let i = departures.length - 1; i >= 0; i -= 1) {\n const d = departures[i];\n const t = new Date(d.time).getTime();\n\n // Only show departures within the next 30 minutes\n if (t > past && t < future) {\n // If 2 trains are boarding at the same platform,\n // remove the older one.\n if (d.state === 'BOARDING') {\n if (platformsBoarding.indexOf(d.platform) === -1) {\n platformsBoarding.push(d.platform);\n } else {\n d.state = 'HIDDEN';\n }\n }\n\n // If two trains with the same line number and destinatin\n // and a departure difference < 1 minute, hide the second one.\n if (\n previousDeparture &&\n d.to[0] === previousDeparture.to[0] &&\n Math.abs(t - previousDeparture.time) < 1000 &&\n d.line.name === previousDeparture.line.name\n ) {\n d.state = 'HIDDEN';\n }\n\n if (/(STOP_CANCELLED|JOURNEY_CANCELLED)/.test(d.state)) {\n d.cancelled = true;\n }\n\n previousDeparture = d;\n previousDeparture.time = t;\n departureArray.unshift(d);\n }\n }\n\n return departureArray;\n }\n\n /**\n * Subscribe to departures channel of a given station.\n *\n * @param {number} stationId UIC of the station.\n * @param {Boolean} sortByMinArrivalTime Sort by minimum arrival time\n * @param {function(departures:Departure[])} onMessage Function called on each message of the channel.\n */\n subscribeDepartures(stationId, sortByMinArrivalTime, onMessage) {\n window.clearTimeout(this.departureUpdateTimeout);\n this.unsubscribeDepartures();\n this.subscribedStationUic = stationId;\n const channel = stationId ? `timetable_${stationId}` : null;\n const departureObject = {};\n this.subscribe(\n channel,\n (data) => {\n if (data.source === channel) {\n const content = data.content || {};\n const tDiff = new Date(content.timestamp).getTime() - Date.now();\n content.timediff = tDiff;\n departureObject[content.call_id] = content;\n\n window.clearTimeout(this.departureUpdateTimeout);\n this.departureUpdateTimeout = window.setTimeout(() => {\n const departures = this.filterDepartures(\n departureObject,\n sortByMinArrivalTime || false,\n );\n onMessage(departures);\n }, 100);\n }\n },\n () => {\n onMessage([]);\n },\n );\n }\n\n /**\n * Unsubscribe from current departures channel.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeDepartures(cb) {\n if (this.subscribedStationUic) {\n this.unsubscribe(`timetable_${this.subscribedStationUic}`, '', cb);\n this.subscribedStationUic = null;\n }\n }\n\n /**\n * Subscribe to the disruptions channel for tenant.\n *\n * @param {function} onMessage Function called on each message of the channel.\n */\n subscribeDisruptions(onMessage) {\n this.subscribe(`${this.prefix}newsticker`, (data) => {\n onMessage(data.content);\n });\n }\n\n /**\n * Unsubscribe disruptions.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeDisruptions(cb) {\n this.unsubscribe(`${this.prefix}newsticker`, '', cb);\n }\n\n /**\n * Return a station with a given uic number and a mode.\n *\n * @param {number} uic UIC of the station.\n * @param {TralisMode} mode Tralis mode.\n * @return {Promise<Station>} A station.\n */\n getStation(uic, mode) {\n const params = {\n channel: `station${getModeSuffix(mode, TralisModes)}`,\n args: uic,\n };\n\n return new Promise((resolve, reject) => {\n this.conn.get(params, (data) => {\n if (data.content) {\n resolve(data.content);\n } else {\n reject();\n }\n });\n });\n }\n\n /**\n * Update the model's station list for a given mode and a bbox.\n *\n * @param {TralisMode} mode Tralis mode.\n * @return {Promise<Array<Station>>} An array of stations.\n */\n getStations(mode) {\n const stations = [];\n const params = {\n channel: `station${getModeSuffix(mode, TralisModes)}`,\n };\n window.clearTimeout(this.stationUpdateTimeout);\n return new Promise((resolve, reject) => {\n this.conn.get(params, (data) => {\n if (data.content) {\n stations.push(data.content);\n window.clearTimeout(this.stationUpdateTimeout);\n /** @ignore */\n this.stationUpdateTimeout = window.setTimeout(() => {\n resolve(stations);\n }, 50);\n } else {\n reject(data.content);\n }\n });\n });\n }\n\n /**\n * Subscribe to stations channel.\n * One message pro station.\n *\n * @param {TralisMode} mode Tralis mode.\n * @param {function(station: Station)} onMessage Function called on each message of the channel.\n */\n subscribeStations(mode, onMessage) {\n this.unsubscribeStations();\n this.subscribe(`station${getModeSuffix(mode, TralisModes)}`, (data) => {\n if (data.content) {\n onMessage(data.content);\n }\n });\n }\n\n /**\n * Unsubscribe to stations channel.\n * @param {function} cb The listener callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribe.\n */\n unsubscribeStations(cb) {\n window.clearTimeout(this.stationUpdateTimeout);\n this.unsubscribe('station', '', cb);\n }\n\n /**\n * Subscribe to extra_geoms channel.\n *\n * @param {function(extraGeoms: GeosJSONFeature[])} onMessage Function called on each message of the channel.\n */\n subscribeExtraGeoms(onMessage) {\n this.subscribe('extra_geoms', (data) => {\n const extraGeom = data.content;\n\n if (extraGeom) {\n const { ref } = extraGeom.properties;\n\n if (extraGeom.type === 'Feature') {\n this.extraGeoms[ref] = extraGeom;\n } else {\n delete this.extraGeoms[ref];\n }\n\n onMessage(\n Object.keys(this.extraGeoms).map((key) => this.extraGeoms[key]),\n );\n }\n });\n }\n\n /**\n * Unsubscribe to extra_geoms channel.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeExtraGeoms(cb) {\n this.unsubscribe('extra_geoms', '', cb);\n }\n\n /**\n * Subscribe to trajectory channel.\n *\n * @param {TralisMode} mode Tralis mode.\n * @param {function(trajectory: TralisTrajectory)} onMessage Function called on each message of the channel.\n * @param {boolean} quiet If true, the subscription will not send GET and SUB requests to the websocket.\n */\n subscribeTrajectory(mode, onMessage, quiet = false) {\n this.unsubscribeTrajectory(onMessage);\n this.subscribe(\n `trajectory${getModeSuffix(mode, TralisModes)}`,\n onMessage,\n null,\n quiet,\n );\n }\n\n /**\n * Unsubscribe to trajectory channels.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeTrajectory(cb) {\n this.unsubscribe(`trajectory`, '', cb);\n }\n\n /**\n * Subscribe to deleted_vhicles channel.\n *\n * @param {TralisMode} mode Tralis mode.\n * @param {function(response: { content: Vehicle })} onMessage Function called on each message of the channel.\n * @param {boolean} quiet If true, the subscription will not send GET and SUB requests to the websocket.\n */\n subscribeDeletedVehicles(mode, onMessage, quiet = false) {\n this.unsubscribeDeletedVehicles(onMessage);\n this.subscribe(\n `deleted_vehicles${getModeSuffix(mode, TralisModes)}`,\n onMessage,\n null,\n quiet,\n );\n }\n\n /**\n * Unsubscribe to deleted_vhicles channels.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeDeletedVehicles(cb) {\n this.unsubscribe('deleted_vehicles', '', cb);\n }\n\n /**\n * Get a full trajectory of a vehicule .\n *\n * @param {string} id A vehicle id.\n * @param {TralisMode} mode Tralis mode.\n * @param {string} generalizationLevel The generalization level to request. Can be one of 5 (more generalized), 10, 30, 100, undefined (less generalized).\n * @return {Promise<FullTrajectory>} Return a full trajectory.\n */\n getFullTrajectory(id, mode, generalizationLevel) {\n const channel = [`full_trajectory${getModeSuffix(mode, TralisModes)}`];\n if (id) {\n channel.push(id);\n }\n\n if ((!mode || mode === TralisModes.TOPOGRAPHIC) && generalizationLevel) {\n channel.push(`gen${generalizationLevel}`);\n }\n\n const params = {\n channel: channel.join('_'),\n };\n\n return new Promise((resolve) => {\n this.conn.get(params, (data) => {\n if (data.content) {\n resolve(data.content);\n }\n });\n });\n }\n\n /**\n * Get full trajectories of a vehicules .\n *\n * @param {string[]} ids List of vehicles ids.\n * @param {TralisMode} mode Tralis mode.\n * @param {string} generalizationLevel The generalization level to request. Can be one of '', 'gen5', 'gen10', 'gen30', 'gen100'.\n * @return {Promise<Array<FullTrajectory>>} Return an array of full trajectories.\n */\n getFullTrajectories(ids, mode, generalizationLevel) {\n const promises = ids.map((id) =>\n this.getFullTrajectory(id, mode, generalizationLevel),\n );\n return Promise.all(promises);\n }\n\n /**\n * Subscribe to full_trajectory channel of a given vehicle.\n *\n * @param {string} id A vehicle id.\n * @param {TralisMode} mode Tralis mode.\n */\n subscribeFullTrajectory(id, mode) {\n // window.clearTimeout(this.fullTrajectoryUpdateTimeout);\n this.unsubscribeFullTrajectory(id);\n this.subscribe(\n `full_trajectory${getModeSuffix(mode, TralisModes)}_${id}`,\n (data) => {\n // eslint-disable-next-line no-console\n console.log('subscribe full_trajectory', data);\n },\n (err) => {\n // eslint-disable-next-line no-console\n console.log('subscribe full_trajectory error', err);\n },\n );\n }\n\n /**\n * Unsubscribe from full_trajectory channel\n *\n * @param {string} id A vehicle id.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeFullTrajectory(id, cb) {\n this.unsubscribe('full_trajectory', `_${id}`, cb);\n }\n\n /**\n * Get the list of stops for this vehicle.\n *\n * @param {string} id A vehicle id.\n * @return {Promise<StopSequence>} Returns a stop sequence object.\n */\n getStopSequence(id) {\n const params = {\n channel: `stopsequence_${id}`,\n };\n return new Promise((resolve, reject) => {\n this.conn.get(\n params,\n (data) => {\n if (data.content && data.content.length) {\n const content = data.content.map((stopSequence) =>\n cleanStopTime(stopSequence),\n );\n\n // Remove the delay from arrivalTime and departureTime\n resolve(content);\n }\n resolve([]);\n },\n (err) => {\n reject(err);\n },\n );\n });\n }\n\n /**\n * Get a list of stops for a list of vehicles.\n *\n * @param {string[]} ids List of vehicles ids.\n * @return {Promise<Array<StopSequence>>} Return an array of stop sequences.\n */\n getStopSequences(ids) {\n const promises = ids.map((id) => this.getStopSequence(id));\n return Promise.all(promises);\n }\n\n /**\n * Subscribe to stopsequence channel of a given vehicle.\n *\n * @param {string} id A vehicle id.\n * @param {function(stopSequence: StopSequence)} onMessage Function called on each message of the channel.\n */\n subscribeStopSequence(id, onMessage) {\n window.clearTimeout(this.fullTrajectoryUpdateTimeout);\n this.unsubscribeStopSequence(id);\n\n this.subscribe(\n `stopsequence_${id}`,\n (data) => {\n if (data.content && data.content.length) {\n const content = data.content.map((stopSequence) =>\n cleanStopTime(stopSequence),\n );\n\n // Remove the delay from arrivalTime and departureTime\n onMessage(content);\n }\n },\n (err) => {\n // eslint-disable-next-line no-console\n console.log('subscribe stopsequence error', err);\n },\n );\n }\n\n /**\n * Unsubscribe from stopsequence channel\n *\n * @param {string} id A vehicle id.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeStopSequence(id, cb) {\n this.unsubscribe(`stopsequence`, `_${id}`, cb);\n }\n\n /**\n * Subscribe to healthcheck channel.\n * @param {function} onMessage Callback when the subscribe to healthcheck channel succeeds.\n */\n subscribeHealthCheck(onMessage) {\n this.unsubscribeHealthCheck();\n this.subscribe('healthcheck', onMessage);\n }\n\n /**\n * Unsubscribe to healthcheck channel.\n */\n unsubscribeHealthCheck() {\n this.unsubscribe('healthcheck');\n }\n}\nexport default TralisAPI;\n","/* eslint-disable no-empty-function */\n/* eslint-disable no-useless-constructor */\n/* eslint-disable no-unused-vars */\n/* eslint-disable class-methods-use-this */\n/* eslint-disable max-classes-per-file */\nimport qs from 'query-string';\nimport { buffer, containsCoordinate, intersects } from 'ol/extent';\nimport { unByKey } from 'ol/Observable';\nimport GeoJSON from 'ol/format/GeoJSON';\nimport Point from 'ol/geom/Point';\nimport debounce from 'lodash.debounce';\nimport throttle from 'lodash.throttle';\nimport { fromLonLat } from 'ol/proj';\nimport Tracker from '../Tracker';\nimport { timeSteps } from '../trackerConfig';\nimport createFilters from '../utils/createTrackerFilters';\nimport trackerDefaultStyle from '../styles/trackerDefaultStyle';\nimport { TralisAPI, TralisModes } from '../../api';\n\n/* Permalink parameter used to filters vehicles */\nconst LINE_FILTER = 'publishedlinename';\nconst ROUTE_FILTER = 'tripnumber';\nconst OPERATOR_FILTER = 'operator';\n\n/**\n * TralisLayerInterface.\n */\nexport class TralisLayerInterface {\n /*\n * Constructor\n\n * @param {Object} options Layer options.\n * @param {string} options.url Tralis service url.\n * @param {string} options.apiKey Access key for [geOps services](https://developer.geops.io/).\n * @param {boolean} [options.debug=false] Display additional debug informations.\n * @param {TralisMode} [options.mode=TralisMode.TOPOGRAPHIC] Tralis's Mode.\n * @param {number} [options.minZoomInterpolation=8] Minimal zoom when trains positions start to be interpolated.\n * @param {number} [options.minZoomNonTrain=9] Minimal zoom when non trains vehicles are allowed to be displayed.\n */\n constructor(options = {}) {}\n\n /**\n * Initialize the layer subscribing to the Tralis api.\n *\n * @param {ol/Map~Map} map\n */\n init(map) {}\n\n /**\n * Terminate the layer unsubscribing to the Tralis api.\n */\n terminate() {}\n\n /**\n * Start the clock.\n */\n start() {}\n\n /**\n * Stop the clock.\n */\n stop() {}\n\n /**\n * Set the Tralis api's bbox.\n *\n * @param {Array<number>} extent Extent to request, [minX, minY, maxX, maxY, zoom].\n * @param {number} zoom Zoom level to request. Must be an integer.\n */\n setBbox(extent, zoom) {}\n\n /**\n * Set the Tralis api's mode.\n *\n * @param {TralisMode} mode Tralis mode\n */\n setMode(mode) {}\n\n /**\n * Request the stopSequence and the fullTrajectory informations for a vehicle.\n *\n * @param {string} id The vehicle identifier (the train_id property).\n * @param {TralisMode} mode The mode to request. If not defined, the layer´s mode propetrty will be used.\n * @return {Promise<{stopSequence: StopSequence, fullTrajectory: FullTrajectory>} A promise that will be resolved with the trajectory informations.\n */\n getTrajectoryInfos(id, mode) {}\n}\n\n/**\n * Mixin for TralisLayerInterface.\n *\n * @param {Class} Base A class to extend with {TralisLayerInterface} functionnalities.\n * @return {Class} A class that implements {TralisLayerInterface} class and extends Base;\n * @private\n */\nconst TralisLayerMixin = (Base) =>\n class extends Base {\n constructor(options = {}) {\n super({ hitTolerance: 10, ...options });\n\n this.debug = options.debug;\n this.mode = options.mode || TralisModes.TOPOGRAPHIC;\n this.api = options.api || new TralisAPI(options);\n this.tenant = options.tenant || ''; // sbb,sbh or sbm\n this.minZoomNonTrain = options.minZoomNonTrain || 9; // Min zoom level from which non trains are allowed to be displayed. Min value is 9 (as configured by the server\n this.minZoomInterpolation = options.minZoomInterpolation || 8; // Min zoom level from which trains positions are not interpolated.\n this.format = new GeoJSON();\n this.generalizationLevelByZoom = options.generalizationLevelByZoom || {\n 0: 5,\n 1: 5,\n 2: 5,\n 3: 5,\n 4: 5,\n 5: 5,\n 6: 5,\n 7: 5,\n 8: 10,\n 9: 30,\n 10: 30,\n 11: 100,\n 12: 100,\n 13: 100,\n };\n\n // This property will call api.setBbox on each movend event\n this.isUpdateBboxOnMoveEnd = options.isUpdateBboxOnMoveEnd !== false;\n\n // Define throttling nad debounce render function\n this.throttleRenderTrajectories = throttle(\n this.renderTrajectoriesInternal,\n 50,\n { leading: false, trailing: true },\n );\n\n this.debounceRenderTrajectories = debounce(\n this.renderTrajectoriesInternal,\n 50,\n { leading: true, trailing: true, maxWait: 5000 },\n );\n\n // Bind callbacks\n this.onFeatureHover = this.onFeatureHover.bind(this);\n this.onFeatureClick = this.onFeatureClick.bind(this);\n this.renderTrajectoriesInternal =\n this.renderTrajectoriesInternal.bind(this);\n this.onTrajectoryMessage = this.onTrajectoryMessage.bind(this);\n this.onDeleteTrajectoryMessage =\n this.onDeleteTrajectoryMessage.bind(this);\n this.onDocumentVisibilityChange =\n this.onDocumentVisibilityChange.bind(this);\n }\n\n /**\n * Define layer's properties.\n *\n * @ignore\n */\n defineProperties(options) {\n // Tracker options use to build the tracker.\n let { regexPublishedLineName, publishedLineName, tripNumber, operator } =\n options;\n const {\n style,\n speed,\n pixelRatio,\n hoverVehicleId,\n selectedVehicleId,\n filter,\n sort,\n time,\n live,\n } = options;\n\n const initTrackerOptions = {\n style,\n };\n\n Object.keys(initTrackerOptions).forEach(\n (key) =>\n initTrackerOptions[key] === undefined &&\n delete initTrackerOptions[key],\n );\n\n let currSpeed = speed || 1;\n let currTime = time || new Date();\n\n super.defineProperties(options);\n\n Object.defineProperties(this, {\n isTrackerLayer: { value: true },\n\n /**\n * Style function used to render a vehicle.\n */\n style: {\n value: (trajectory, viewState) =>\n (style || trackerDefaultStyle)(trajectory, viewState, this),\n },\n\n /**\n * Speed of the wheel of time.\n * If live property is true. The speed is ignored.\n */\n speed: {\n get: () => currSpeed,\n set: (newSpeed) => {\n currSpeed = newSpeed;\n this.start();\n },\n },\n\n /**\n * Function to filter which vehicles to display.\n */\n filter: {\n value: filter,\n writable: true,\n },\n\n /**\n * Function to sort the vehicles to display.\n */\n sort: {\n value: sort,\n writable: true,\n },\n\n /**\n * The tracker that renders the trajectories.\n */\n tracker: { value: null, writable: true },\n\n /**\n * Canvas cache object for trajectories drawn.\n */\n styleCache: { value: {} },\n\n /**\n * If true. The layer will always use Date.now() on the next tick to render the trajectories.\n * When true, setting the time property has no effect.\n */\n live: {\n value: live === false ? live : true,\n writable: true,\n },\n\n /**\n * Time used to display the trajectories. Can be a Date or a number in ms representing a Date.\n * If live property is true. The setter does nothing.\n */\n time: {\n get: () => currTime,\n set: (newTime) => {\n currTime = newTime && newTime.getTime ? newTime : new Date(newTime);\n this.renderTrajectories();\n },\n },\n\n /**\n * Keep track of which trajectories are stored.\n */\n trajectories: {\n value: {},\n writable: true,\n },\n\n /**\n * Keep track of which trajectories are currently drawn.\n */\n renderedTrajectories: {\n get: () => (this.tracker && this.tracker.renderedTrajectories) || [],\n },\n\n /**\n * Id of the hovered vehicle.\n */\n hoverVehicleId: {\n value: hoverVehicleId,\n writable: true,\n },\n\n /**\n * Id of the selected vehicle.\n */\n selectedVehicleId: {\n value: selectedVehicleId,\n writable: true,\n },\n\n /**\n * Id of the selected vehicle.\n */\n pixelRatio: {\n value:\n pixelRatio ||\n (typeof window !== 'undefined' ? window.devicePixelRatio : 1),\n writable: true,\n },\n\n /**\n * Options used by the constructor of the Tracker class.\n */\n initTrackerOptions: {\n value: initTrackerOptions,\n writable: false,\n },\n\n /**\n * If true, encapsulates the renderTrajectories calls in a requestAnimationFrame.\n */\n useRequestAnimationFrame: {\n value: options.useRequestAnimationFrame || false,\n writable: true,\n },\n\n /**\n * If true, encapsulates the renderTrajectories calls in a throttle function. Default to true.\n */\n useThrottle: {\n value: options.useThrottle || true,\n writable: true,\n },\n\n /**\n * If true, encapsulates the renderTrajectories calls in a debounce function.\n */\n useDebounce: {\n value: options.useDebounce || false,\n writable: true,\n },\n\n /**\n * Filter properties used in combination with permalink parameters.\n */\n publishedLineName: {\n get: () => publishedLineName,\n set: (newPublishedLineName) => {\n publishedLineName = newPublishedLineName;\n this.updateFilters();\n },\n },\n tripNumber: {\n get: () => tripNumber,\n set: (newTripNumber) => {\n tripNumber = newTripNumber;\n this.updateFilters();\n },\n },\n operator: {\n get: () => operator,\n set: (newOperator) => {\n operator = newOperator;\n this.updateFilters();\n },\n },\n regexPublishedLineName: {\n get: () => regexPublishedLineName,\n set: (newRegex) => {\n regexPublishedLineName = newRegex;\n this.updateFilters();\n },\n },\n\n /**\n * Style properties.\n */\n delayDisplay: {\n value: options.delayDisplay || 300000,\n writable: true,\n },\n delayOutlineColor: {\n value: options.delayOutlineColor || '#000000',\n writable: true,\n },\n\n /**\n * Debug properties.\n */\n // Not used anymore, but could be useful for debugging.\n // showVehicleTraj: {\n // value:\n // options.showVehicleTraj !== undefined\n // ? options.showVehicleTraj\n // : true,\n // writable: true,\n // },\n });\n\n // Update filter function based on convenient properties\n this.updateFilters();\n }\n\n init(map) {\n super.init(map);\n\n this.tracker = new Tracker({\n style: (...args) => this.style(...args),\n ...this.initTrackerOptions,\n });\n\n // If the layer is visible we start the rendering clock\n if (this.visible) {\n this.start();\n }\n\n // On change of visibility we start/stop the rendering clock\n this.visibilityRef = this.on('change:visible', (evt) => {\n if (evt.target.visible) {\n this.start();\n } else {\n this.stop();\n }\n });\n\n // To avoid browser hanging when the tab is not visible for a certain amount of time,\n // We stop the rendering and the websocket when hide and start again when show.\n document.addEventListener(\n 'visibilitychange',\n this.onDocumentVisibilityChange,\n );\n }\n\n terminate() {\n document.removeEventListener(\n 'visibilitychange',\n this.onDocumentVisibilityChange,\n );\n\n this.stop();\n unByKey(this.visibilityRef);\n if (this.tracker) {\n const { canvas } = this.tracker;\n const context = canvas.getContext('2d');\n context.clearRect(0, 0, canvas.width, canvas.height);\n this.tracker = null;\n }\n super.terminate();\n }\n\n start() {\n this.stop();\n this.renderTrajectories();\n this.startUpdateTime();\n\n if (this.isClickActive) {\n this.onClick(this.onFeatureClick);\n }\n\n if (this.isHoverActive) {\n this.onHover(this.onFeatureHover);\n }\n\n this.api.open();\n this.api.subscribeTrajectory(\n this.mode,\n this.onTrajectoryMessage,\n this.isUpdateBboxOnMoveEnd,\n );\n this.api.subscribeDeletedVehicles(\n this.mode,\n this.onDeleteTrajectoryMessage,\n this.isUpdateBboxOnMoveEnd,\n );\n\n if (this.isUpdateBboxOnMoveEnd) {\n // Update the bbox on each move end\n this.setBbox();\n }\n }\n\n /**\n * Start the clock.\n * @private\n */\n startUpdateTime() {\n this.stopUpdateTime();\n this.updateTimeDelay = this.getRefreshTimeInMs();\n this.updateTimeInterval = setInterval(() => {\n // When live=true, we update the time with new Date();\n this.time = this.live\n ? new Date()\n : this.time.getTime() + this.updateTimeDelay * this.speed;\n }, this.updateTimeDelay);\n }\n\n stop() {\n this.api.unsubscribeTrajectory(this.onTrajectoryMessage);\n this.api.unsubscribeDeletedVehicles(this.onDeleteTrajectoryMessage);\n this.api.close();\n }\n\n /**\n * Stop the clock.\n * @private\n */\n stopUpdateTime() {\n if (this.updateTimeInterval) {\n clearInterval(this.updateTimeInterval);\n }\n }\n\n /**\n * Launch renderTrajectories. it avoids duplicating code in renderTrajectories method.\n *\n * @param {object} viewState The view state of the map.\n * @param {number[2]} viewState.center Center coordinate of the map in mercator coordinate.\n * @param {number[4]} viewState.extent Extent of the map in mercator coordinates.\n * @param {number[2]} viewState.size Size ([width, height]) of the canvas to render.\n * @param {number} [viewState.rotation = 0] Rotation of the map to render.\n * @param {number} viewState.resolution Resolution of the map to render.\n * @param {boolean} noInterpolate If true trajectories are not interpolated but\n * drawn at the last known coordinate. Use this for performance optimization\n * during map navigation.\n * @private\n */\n renderTrajectoriesInternal(viewState, noInterpolate) {\n if (!this.tracker) {\n return false;\n }\n\n const time = this.live ? Date.now() : this.time;\n\n const trajectories = Object.values(this.trajectories);\n\n // console.time('sort');\n if (this.sort) {\n trajectories.sort(this.sort);\n }\n // console.timeEnd('sort');\n\n // console.time('render');\n this.renderState = this.tracker.renderTrajectories(\n trajectories,\n { ...viewState, pixelRatio: this.pixelRatio, time },\n {\n noInterpolate:\n viewState.zoom < this.minZoomInterpolation ? true : noInterpolate,\n hoverVehicleId: this.hoverVehicleId,\n selectedVehicleId: this.selectedVehicleId,\n iconScale: this.iconScale,\n delayDisplay: this.delayDisplay,\n delayOutlineColor: this.delayOutlineColor,\n },\n );\n\n // console.timeEnd('render');\n return true;\n }\n\n /**\n * Render the trajectories requesting an animation frame and cancelling the previous one.\n * This function must be overrided by children to provide the correct parameters.\n *\n * @param {object} viewState The view state of the map.\n * @param {number[2]} viewState.center Center coordinate of the map in mercator coordinate.\n * @param {number[4]} viewState.extent Extent of the map in mercator coordinates.\n * @param {number[2]} viewState.size Size ([width, height]) of the canvas to render.\n * @param {number} [viewState.rotation = 0] Rotation of the map to render.\n * @param {number} viewState.resolution Resolution of the map to render.\n * @param {boolean} noInterpolate If true trajectories are not interpolated but\n * drawn at the last known coordinate. Use this for performance optimization\n * during map navigation.\n * @private\n */\n renderTrajectories(viewState, noInterpolate) {\n if (this.requestId) {\n cancelAnimationFrame(this.requestId);\n this.requestId = null;\n }\n\n if (!noInterpolate && this.useRequestAnimationFrame) {\n this.requestId = requestAnimationFrame(() => {\n this.renderTrajectoriesInternal(viewState, noInterpolate);\n });\n } else if (!noInterpolate && this.useDebounce) {\n this.debounceRenderTrajectories(viewState, noInterpolate);\n } else if (!noInterpolate && this.useThrottle) {\n this.throttleRenderTrajectories(viewState, noInterpolate);\n } else {\n this.renderTrajectoriesInternal(viewState, noInterpolate);\n }\n }\n\n setBbox(extent, zoom) {\n // Clean trajectories before sending the new bbox\n // Purge trajectories:\n // - which are outside the extent\n // - when it's bus and zoom level is too low for them\n const keys = Object.keys(this.trajectories);\n for (let i = keys.length - 1; i >= 0; i -= 1) {\n this.purgeTrajectory(this.trajectories[keys[i]], extent, zoom);\n }\n\n const bbox = [...extent];\n\n if (this.isUpdateBboxOnMoveEnd) {\n bbox.push(zoom);\n\n if (this.tenant) {\n bbox.push(`tenant=${this.tenant}`);\n }\n\n /* @ignore */\n this.generalizationLevel = this.generalizationLevelByZoom[zoom];\n if (this.generalizationLevel) {\n bbox.push(`gen=${this.generalizationLevel}`);\n }\n }\n\n this.api.bbox = bbox;\n }\n\n setMode(mode) {\n if (this.mode === mode) {\n return;\n }\n this.mode = mode;\n this.api.subscribeTrajectory(\n this.mode,\n this.onTrajectoryMessage,\n this.isUpdateBboxOnMoveEnd,\n );\n this.api.subscribeDeletedVehicles(\n this.mode,\n this.onDeleteTrajectoryMessage,\n this.isUpdateBboxOnMoveEnd,\n );\n }\n\n /**\n * Get the duration before the next update depending on zoom level.\n *\n * @private\n * @param {number} zoom\n */\n getRefreshTimeInMs(zoom) {\n const roundedZoom = Math.round(zoom);\n const timeStep = timeSteps[roundedZoom] || 25;\n const nextTick = Math.max(25, timeStep / this.speed);\n const nextThrottleTick = Math.min(nextTick, 500);\n // TODO: see if this should go elsewhere.\n if (this.useThrottle) {\n this.throttleRenderTrajectories = throttle(\n this.renderTrajectoriesInternal,\n nextThrottleTick,\n { leading: true, trailing: true },\n );\n } else if (this.useDebounce) {\n this.debounceRenderTrajectories = debounce(\n this.renderTrajectoriesInternal,\n nextThrottleTick,\n { leading: true, trailing: true, maxWait: 5000 },\n );\n }\n if (this.api?.buffer) {\n const [, size] = this.api.buffer;\n this.api.buffer = [nextThrottleTick, size];\n }\n return nextTick;\n }\n\n /**\n * Get vehicle.\n * @param {function} filterFc A function use to filter results.\n * @return {Array<Object>} Array of vehicle.\n */\n getVehicle(filterFc) {\n return Object.values(this.trajectories).filter(filterFc);\n }\n\n /**\n * Request feature information for a given coordinate.\n *\n * @param {ol/coordinate~Coordinate} coordinate Coordinate.\n * @param {Object} options Options See child classes to see which options are supported.\n * @param {number} [options.resolution=1] The resolution of the map.\n * @param {number} [options.nb=Infinity] The max number of vehicles to return.\n * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.\n */\n getFeatureInfoAtCoordinate(coordinate, options = {}) {\n const { resolution, nb } = options;\n const ext = buffer(\n [...coordinate, ...coordinate],\n this.hitTolerance * resolution,\n );\n let trajectories = Object.values(this.trajectories);\n\n if (this.sort) {\n trajectories = trajectories.sort(this.sort);\n }\n\n const vehicles = [];\n for (let i = 0; i < trajectories.length; i += 1) {\n if (\n trajectories[i].properties.coordinate &&\n containsCoordinate(ext, trajectories[i].properties.coordinate)\n ) {\n vehicles.push(trajectories[i]);\n }\n if (vehicles.length === nb) {\n break;\n }\n }\n\n return Promise.resolve({\n layer: this,\n features: vehicles.map((vehicle) => this.format.readFeature(vehicle)),\n coordinate,\n });\n }\n\n /**\n * Request the stopSequence and the fullTrajectory informations for a vehicle.\n *\n * @param {string} id The vehicle identifier (the train_id property).\n * @return {Promise<{stopSequence: StopSequence, fullTrajectory: FullTrajectory>} A promise that will be resolved with the trajectory informations.\n */\n getTrajectoryInfos(id) {\n // When a vehicle is selected, we request the complete stop sequence and the complete full trajectory.\n // Then we combine them in one response and send them to inherited layers.\n const promises = [\n this.api.getStopSequence(id, this.mode),\n this.api.getFullTrajectory(id, this.mode, this.generalizationLevel),\n ];\n\n return Promise.all(promises).then(([stopSequence, fullTrajectory]) => {\n const response = {\n stopSequence,\n fullTrajectory,\n };\n return response;\n });\n }\n\n /**\n * Determine if the trajectory is useless and should be removed from the list or not.\n * By default, this function exclude vehicles:\n * - that have their trajectory outside the current extent and\n * - that are not a train and zoom level is lower than layer's minZoomNonTrain property.\n *\n * @param {TralisTrajectory} trajectory\n * @param {Array<number>} extent\n * @param {number} zoom\n * @return {boolean} if the trajectory must be displayed or not.\n * @ignore\n */\n purgeTrajectory(trajectory, extent, zoom) {\n const { type, bounds, train_id: id } = trajectory.properties;\n if (\n !intersects(extent, bounds) ||\n (type !== 'rail' && zoom < (this.minZoomNonTrain || 9))\n ) {\n this.removeTrajectory(id);\n return true;\n }\n return false;\n }\n\n /**\n * Add a trajectory to the tracker.\n * @param {TralisTrajectory} trajectory The trajectory to add.\n * @private\n */\n addTrajectory(trajectory) {\n if (this.filter && !this.filter(trajectory)) {\n return;\n }\n this.trajectories[trajectory.properties.train_id] = trajectory;\n this.renderTrajectories();\n }\n\n removeTrajectory(id) {\n delete this.trajectories[id];\n }\n\n /**\n * On zoomend we adjust the time interval of the update of vehicles positions.\n *\n * @param evt Event that triggered the function.\n * @private\n */\n // eslint-disable-next-line no-unused-vars\n onZoomEnd(evt) {\n this.startUpdateTime();\n }\n\n onDocumentVisibilityChange() {\n if (!this.visible) {\n return;\n }\n if (document.hidden) {\n this.stop();\n } else {\n this.start();\n }\n }\n\n /**\n * Callback on websocket's trajectory channel events.\n * It adds a trajectory to the list.\n *\n * @private\n */\n onTrajectoryMessage(data) {\n if (!data.content) {\n return;\n }\n const trajectory = data.content;\n\n const {\n geometry,\n properties: {\n train_id: id,\n time_since_update: timeSinceUpdate,\n raw_coordinates: rawCoordinates,\n },\n } = trajectory;\n\n // ignore old events [SBAHNM-97]\n if (timeSinceUpdate < 0) {\n return;\n }\n\n // console.time(`onTrajectoryMessage${data.content.properties.train_id}`);\n if (this.purgeTrajectory(trajectory)) {\n return;\n }\n\n if (\n this.debug &&\n this.mode === TralisModes.TOPOGRAPHIC &&\n rawCoordinates\n ) {\n trajectory.properties.olGeometry = {\n type: 'Point',\n coordinates: fromLonLat(\n rawCoordinates,\n this.map.getView().getProjection(),\n ),\n };\n } else {\n trajectory.properties.olGeometry = this.format.readGeometry(geometry);\n }\n\n // TODO Make sure the timeOffset is useful. May be we can remove it.\n trajectory.properties.timeOffset = Date.now() - data.timestamp;\n this.addTrajectory(trajectory);\n }\n\n /**\n * Callback on websocket's deleted_vehicles channel events.\n * It removes the trajectory from the list.\n *\n * @private\n * @override\n */\n onDeleteTrajectoryMessage(data) {\n if (!data.content) {\n return;\n }\n\n this.removeTrajectory(data.content);\n }\n\n /**\n * Callback when user moves the mouse/pointer over the map.\n * It sets the layer's hoverVehicleId property with the current hovered vehicle's id.\n *\n * @private\n * @override\n */\n onFeatureHover(features, layer, coordinate) {\n const [feature] = features;\n let id = null;\n if (feature) {\n id = feature.get('train_id');\n }\n if (this.hoverVehicleId !== id) {\n /** @ignore */\n this.hoverVehicleId = id;\n this.renderTrajectories(true);\n }\n }\n\n /**\n * Callback when user clicks on the map.\n * It sets the layer's selectedVehicleId property with the current selected vehicle's id.\n *\n * @private\n * @override\n */\n onFeatureClick(features, layer, coordinate) {\n const [feature] = features;\n let id = null;\n if (feature) {\n id = feature.get('train_id');\n }\n if (this.selectedVehicleId !== id) {\n /** @ignore */\n this.selectedVehicleId = id;\n this.selectedVehicle = feature;\n this.renderTrajectories(true);\n }\n }\n\n /**\n * Update filter provided by properties or permalink.\n */\n updateFilters() {\n // Setting filters from the permalink if no values defined by the layer.\n const parameters = qs.parse(window.location.search.toLowerCase());\n const publishedName = this.publishedLineName || parameters[LINE_FILTER];\n const tripNumber = this.tripNumber || parameters[ROUTE_FILTER];\n const operator = this.operator || parameters[OPERATOR_FILTER];\n const { regexPublishedLineName } = this;\n\n // Only overrides filter function if one of this property exists.\n if (publishedName || tripNumber || operator || regexPublishedLineName) {\n // filter is the property in TrackerLayerMixin.\n this.filter = createFilters(\n publishedName,\n tripNumber,\n operator,\n regexPublishedLineName,\n );\n }\n }\n };\n\nexport default TralisLayerMixin;\n","import { Style, Fill, Stroke, Circle } from 'ol/style';\nimport { getBgColor } from '../../common/trackerConfig';\n\nconst borderStyle = new Style({\n zIndex: 2,\n image: new Circle({\n radius: 5,\n fill: new Fill({\n color: '#000000',\n }),\n }),\n stroke: new Stroke({\n color: '#000000',\n width: 6,\n }),\n});\n\nconst fullTrajectorystyle = (feature) => {\n let lineColor = '#ffffff'; // white\n\n const type = feature.get('type');\n let stroke = feature.get('stroke');\n\n if (stroke && stroke[0] !== '#') {\n stroke = `#${stroke}`;\n }\n\n lineColor = stroke || getBgColor(type);\n\n // Don't allow white lines, use red instead.\n lineColor = /#ffffff/i.test(lineColor) ? '#ff0000' : lineColor;\n\n const style = [\n borderStyle,\n new Style({\n zIndex: 3,\n image: new Circle({\n radius: 4,\n fill: new Fill({\n color: lineColor,\n }),\n }),\n stroke: new Stroke({\n color: lineColor,\n width: 4,\n }),\n }),\n ];\n return style;\n};\nexport default fullTrajectorystyle;\n","import { Style, Fill, Stroke, Circle } from 'ol/style';\n\nconst stroke = new Style({\n zIndex: 2,\n image: new Circle({\n radius: 5,\n fill: new Fill({\n color: '#000000',\n }),\n }),\n stroke: new Stroke({\n color: '#000000',\n width: 6,\n }),\n});\n\nconst fill = new Style({\n zIndex: 3,\n image: new Circle({\n radius: 4,\n fill: new Fill({\n color: '#a0a0a0',\n }),\n }),\n stroke: new Stroke({\n color: '#a0a0a0',\n width: 4,\n }),\n});\n\nconst fullTrajectoryDelaystyle = () => {\n return [stroke, fill];\n};\n\nexport default fullTrajectoryDelaystyle;\n","import GeoJSON from 'ol/format/GeoJSON';\nimport { Layer as OLLayer, Group, Vector as VectorLayer } from 'ol/layer';\nimport Source from 'ol/source/Source';\nimport { composeCssTransform } from 'ol/transform';\nimport { Vector as VectorSource } from 'ol/source';\nimport Layer from './Layer';\nimport mixin from '../../common/mixins/TralisLayerMixin';\nimport { fullTrajectoryStyle } from '../styles';\n\nconst format = new GeoJSON();\n\n/**\n * Responsible for loading and display data from a Tralis service.\n *\n * @example\n * import { TralisLayer } from 'mobility-toolbox-js/ol';\n *\n * const layer = new TralisLayer({\n * url: [yourUrl],\n * apiKey: [yourApiKey],\n * });\n *\n *\n * @see <a href=\"/api/class/src/api/tralis/TralisAPI%20js~TralisAPI%20html\">TralisAPI</a>\n *\n * @extends {Layer}\n * @implements {TralisLayerInterface}\n */\nclass TralisLayer extends mixin(Layer) {\n /**\n * Constructor.\n *\n * @param {Object} options\n * @private\n */\n constructor(options = {}) {\n // We use a group to be able to add custom vector layer in extended class.\n // For example TrajservLayer use a vectorLayer to display the complete trajectory.\n super({\n ...options,\n });\n\n /** @ignore */\n this.olLayer =\n options.olLayer ||\n new Group({\n layers: [\n new VectorLayer({\n source: new VectorSource({ features: [] }),\n style: options.fullTrajectoryStyle || fullTrajectoryStyle,\n }),\n new OLLayer({\n source: new Source({}),\n render: (frameState) => {\n if (!this.tracker || !this.tracker.canvas) {\n return null;\n }\n\n if (!this.container) {\n this.container = document.createElement('div');\n this.container.style.position = 'absolute';\n this.container.style.width = '100%';\n this.container.style.height = '100%';\n this.transformContainer = document.createElement('div');\n this.transformContainer.style.position = 'absolute';\n this.transformContainer.style.width = '100%';\n this.transformContainer.style.height = '100%';\n this.container.appendChild(this.transformContainer);\n this.tracker.canvas.style.position = 'absolute';\n this.tracker.canvas.style.top = '0';\n this.tracker.canvas.style.left = '0';\n this.tracker.canvas.style.transformOrigin = 'top left';\n this.transformContainer.appendChild(this.tracker.canvas);\n }\n\n if (this.renderedViewState) {\n const { center, resolution, rotation } = frameState.viewState;\n const {\n center: renderedCenter,\n resolution: renderedResolution,\n rotation: renderedRotation,\n } = this.renderedViewState;\n\n if (renderedResolution / resolution >= 3) {\n // Avoid having really big points when zooming fast.\n const { canvas } = this.tracker;\n const context = canvas.getContext('2d');\n context.clearRect(0, 0, canvas.width, canvas.height);\n } else {\n const pixelCenterRendered =\n this.map.getPixelFromCoordinate(renderedCenter);\n const pixelCenter = this.map.getPixelFromCoordinate(center);\n this.transformContainer.style.transform = composeCssTransform(\n pixelCenterRendered[0] - pixelCenter[0],\n pixelCenterRendered[1] - pixelCenter[1],\n renderedResolution / resolution,\n renderedResolution / resolution,\n rotation - renderedRotation,\n 0,\n 0,\n );\n }\n }\n return this.container;\n },\n }),\n ],\n });\n\n // We store the layer used to highlight the full Trajectory\n this.vectorLayer = this.olLayer.getLayers().item(0);\n\n // Options the last render run did happen. If something changes\n // we have to render again\n /** @ignore */\n this.renderState = {\n center: [0, 0],\n zoom: null,\n rotation: 0,\n };\n }\n\n init(map) {\n super.init(map);\n if (this.map) {\n this.olListenersKeys.push(\n this.map.on(['moveend', 'change:target'], (evt) => {\n const view = this.map.getView();\n if (view.getAnimating() || view.getInteracting()) {\n return;\n }\n const zoom = view.getZoom();\n\n // Update the interval between render updates\n if (this.currentZoom !== zoom) {\n this.onZoomEnd(evt);\n }\n this.currentZoom = zoom;\n\n this.onMoveEnd(evt);\n }),\n );\n }\n }\n\n /**\n * Destroy the container of the tracker.\n */\n terminate() {\n super.terminate();\n this.container = null;\n }\n\n /**\n * Detect in the canvas if there is data to query at a specific coordinate.\n * @param {ol/coordinate~Coordinate} coordinate The coordinate to test\n * @returns\n */\n hasFeatureInfoAtCoordinate(coordinate) {\n if (this.map && this.tracker && this.tracker.canvas) {\n const context = this.tracker.canvas.getContext('2d');\n const pixel = this.map.getPixelFromCoordinate(coordinate);\n return !!context.getImageData(\n pixel[0] * this.pixelRatio,\n pixel[1] * this.pixelRatio,\n 1,\n 1,\n ).data[3];\n }\n return false;\n }\n\n /**\n * Render the trajectories using current map's size, resolution and rotation.\n * @param {boolean} noInterpolate if true, renders the vehicles without interpolating theirs positions.\n * @overrides\n */\n renderTrajectories(noInterpolate) {\n const view = this.map.getView();\n super.renderTrajectories(\n {\n size: this.map.getSize(),\n center: this.map.getView().getCenter(),\n extent: view.calculateExtent(),\n resolution: view.getResolution(),\n rotation: view.getRotation(),\n zoom: view.getZoom(),\n pixelRatio: this.pixelRatio,\n },\n noInterpolate,\n );\n }\n\n /**\n * Launch renderTrajectories. it avoids duplicating code in renderTrajectories methhod.\n * @private\n * @override\n */\n renderTrajectoriesInternal(viewState, noInterpolate) {\n let isRendered = false;\n\n const blockRendering =\n this.map.getView().getAnimating() || this.map.getView().getInteracting();\n\n // Don't render the map when the map is animating or interacting.\n isRendered = blockRendering\n ? false\n : super.renderTrajectoriesInternal(viewState, noInterpolate);\n\n // We update the current render state.\n if (isRendered) {\n this.renderedViewState = { ...viewState };\n\n if (this.transformContainer) {\n this.transformContainer.style.transform = '';\n }\n }\n }\n\n /**\n * Return the delay in ms before the next rendering.\n */\n getRefreshTimeInMs() {\n return super.getRefreshTimeInMs(this.map.getView().getZoom());\n }\n\n getFeatureInfoAtCoordinate(coordinate, options = {}) {\n const resolution = this.map.getView().getResolution();\n return super.getFeatureInfoAtCoordinate(coordinate, {\n resolution,\n ...options,\n });\n }\n\n /**\n * On move end we update the websocket with the new bbox.\n *\n * @param {ol/MapEvent~MapEvent} evt Moveend event\n * @private\n * @override\n */\n onMoveEnd() {\n if (this.visible && this.isUpdateBboxOnMoveEnd) {\n this.setBbox();\n }\n\n if (\n this.visible &&\n this.isUpdateBboxOnMoveEnd &&\n this.isClickActive &&\n this.selectedVehicleId\n ) {\n this.highlightTrajectory(this.selectedVehicleId);\n }\n }\n\n /**\n * Function called on moveend event only when the zoom has changed.\n *\n * @param {ol/MapEvent~MapEvent} evt Moveend event.\n * @private\n * @override\n */\n // eslint-disable-next-line no-unused-vars\n onZoomEnd(evt) {\n super.onZoomEnd(evt);\n }\n\n /**\n * Update the cursor style when hovering a vehicle.\n *\n * @private\n * @override\n */\n onFeatureHover(features, layer, coordinate) {\n super.onFeatureHover(features, layer, coordinate);\n this.map.getTargetElement().style.cursor = features.length\n ? 'pointer'\n : 'auto';\n }\n\n /**\n * Display the complete trajectory of the vehicle.\n *\n * @private\n * @override\n */\n onFeatureClick(features, layer, coordinate) {\n super.onFeatureClick(features, layer, coordinate);\n if (!features.length && this.vectorLayer) {\n this.vectorLayer.getSource().clear();\n }\n if (this.selectedVehicleId) {\n this.highlightTrajectory(this.selectedVehicleId);\n }\n }\n\n /**\n * Remove the trajectory form the list if necessary.\n *\n * @private\n */\n purgeTrajectory(trajectory, extent, zoom) {\n return super.purgeTrajectory(\n trajectory,\n extent || this.map.getView().calculateExtent(),\n zoom || this.map.getView().getZoom(),\n );\n }\n\n /**\n * Send the current bbox to the websocket\n *\n * @private\n */\n setBbox(extent, zoom) {\n let newExtent = extent;\n let newZoom = zoom;\n if (!newExtent && this.isUpdateBboxOnMoveEnd) {\n newExtent = extent || this.map.getView().calculateExtent();\n newZoom = Math.floor(this.map.getView().getZoom());\n }\n super.setBbox(newExtent, newZoom);\n }\n\n /**\n * Highlight the trajectory of journey.\n * @private\n */\n highlightTrajectory(id) {\n this.api\n .getFullTrajectory(id, this.mode, this.generalizationLevel)\n .then((fullTrajectory) => {\n const vectorSource = this.vectorLayer.getSource();\n vectorSource.clear();\n\n if (\n !fullTrajectory ||\n !fullTrajectory.features ||\n !fullTrajectory.features.length\n ) {\n return;\n }\n const features = format.readFeatures(fullTrajectory);\n this.vectorLayer.getSource().addFeatures(features);\n });\n }\n\n /**\n * Create a copy of the TralisLayer.\n * @param {Object} newOptions Options to override\n * @return {TralisLayer} A TralisLayer\n */\n clone(newOptions) {\n return new TralisLayer({ ...this.options, ...newOptions });\n }\n}\n\nexport default TralisLayer;\n","import Layer from './Layer';\n\n/**\n * A class use to display vector data.\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass VectorLayer extends Layer {\n /**\n * Request feature information for a given coordinate.\n * @param {ol/coordinate~Coordinate} coordinate the coordinate to request the information at.\n * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.\n */\n getFeatureInfoAtCoordinate(coordinate) {\n let features = [];\n\n if (this.map) {\n const pixel = this.map.getPixelFromCoordinate(coordinate);\n features = this.map.getFeaturesAtPixel(pixel, {\n layerFilter: (l) => l === this.olLayer,\n hitTolerance: this.hitTolerance,\n });\n }\n\n return Promise.resolve({\n features,\n layer: this,\n coordinate,\n });\n }\n\n /**\n * Create a copy of the VectorLayer.\n * @param {Object} newOptions Options to override\n * @return {VectorLayer} A VectorLayer\n */\n clone(newOptions) {\n return new VectorLayer({ ...this.options, ...newOptions });\n }\n}\n\nexport default VectorLayer;\n","import GeoJSON from 'ol/format/GeoJSON';\nimport Layer from './Layer';\n\n/**\n * Class use to display a WMS layer.\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass WMSLayer extends Layer {\n /**\n * @override\n */\n constructor(options = {}) {\n super(options);\n\n /** @ignore */\n this.abortController = new AbortController();\n /** @ignore */\n this.format = new GeoJSON();\n }\n\n /**\n * Get features infos' Url.\n * @param {ol/coordinate~Coordinate} coord\n * @return {ol/layer/Layer~Layer}\n */\n getFeatureInfoUrl(coord) {\n const projection = this.map.getView().getProjection();\n const resolution = this.map.getView().getResolution();\n\n if (this.olLayer.getSource().getFeatureInfoUrl) {\n return this.olLayer\n .getSource()\n .getFeatureInfoUrl(coord, resolution, projection, {\n info_format: 'application/json',\n query_layers: this.olLayer.getSource().getParams().layers,\n });\n }\n return false;\n }\n\n /**\n * Request feature information for a given coordinate.\n * @param {ol/coordinate~Coordinate} coordinate to request the information at.\n * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.\n */\n getFeatureInfoAtCoordinate(coordinate) {\n this.abortController.abort();\n this.abortController = new AbortController();\n const { signal } = this.abortController;\n return fetch(this.getFeatureInfoUrl(coordinate), { signal })\n .then((resp) => resp.json())\n .then((r) => r.features)\n .then((data) => ({\n layer: this,\n coordinate,\n features: data.map((d) => this.format.readFeature(d)),\n }))\n .catch(() =>\n // resolve an empty feature array something fails\n Promise.resolve({\n features: [],\n coordinate,\n layer: this,\n }),\n );\n }\n\n /**\n * Create a copy of the WMSLayer.\n * @param {Object} newOptions Options to override\n * @return {WMSLayer} A WMSLayer\n */\n clone(newOptions) {\n return new WMSLayer({ ...this.options, ...newOptions });\n }\n}\n\nexport default WMSLayer;\n","import BaseObject from 'ol/Object';\n\n/**\n * A class representing a control to display on map.\n *\n * @example\n * const control = new Control();\n *\n * @classproperty {ol/Map~Map|mapboxgl.Map} map - The map which the control refers to.\n * @classproperty {boolean} active - Active the control.\n * @classproperty {HTMLElement} element - The HTML element used to render the control.\n * @classproperty {HTMLElement} target - The HTML element where to render the element property. Default is the map's element. Read only.\n */\nclass Control extends BaseObject {\n /**\n * Constructor\n *\n * @param {Object} [options] Control options.\n * @param {boolean} [options.active = true] Whether the control is active or not.\n * @param {HTMLElement} [options.element] The HTML element used to render the control.\n * @param {HTMLElement} [options.target] The HTML element where to render the element property. Default is the map's element.\n * @param {function} [options.render] Render function called whenever the control needs to be rerendered.\n */\n constructor(options = {}) {\n super(options);\n this.defineProperties(options);\n\n const { active } = {\n active: options.active !== false,\n ...options,\n };\n\n /**\n * @ignore\n */\n this.active = active;\n }\n\n /**\n * Define control's properties.\n *\n * @private\n */\n defineProperties(options) {\n const { target, element, render } = {\n ...options,\n };\n\n Object.defineProperties(this, {\n active: {\n get: () => this.get('active'),\n set: (newActive) => {\n this.set('active', newActive);\n if (newActive) {\n this.activate();\n } else {\n this.deactivate();\n }\n this.render();\n },\n },\n map: {\n get: () => this.get('map'),\n set: (map) => {\n // Remove previous node.\n if (this.map && this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n\n // Clean listeners\n this.deactivate();\n\n this.set('map', map);\n\n if (this.map) {\n // Add new node\n const targett =\n this.target ||\n (this.map.getTargetElement && this.map.getTargetElement()) ||\n (this.map.getContainer && this.map.getContainer());\n\n if (!this.element) {\n this.createDefaultElement();\n }\n\n if (this.element) {\n targett.appendChild(this.element);\n }\n\n // Add listeners\n if (this.active) {\n this.activate();\n }\n }\n this.render();\n },\n },\n target: {\n value: target,\n },\n element: {\n value: element,\n writable: true,\n },\n render: {\n /** @ignore */\n value: render || this.render,\n writable: true,\n },\n });\n }\n\n /**\n * Add listeners then renders the control.\n * To be defined in inherited classes.\n */\n activate() {\n this.deactivate();\n }\n\n /**\n * Remove listeners added by activate() function then renders the control.\n * To be defined in inherited classes.\n */\n // eslint-disable-next-line class-methods-use-this\n deactivate() {}\n\n /**\n * The default render function. It renders content in the HTML element.\n * To be defined in inherited classes.\n *\n * @private\n */\n render() {}\n\n /**\n * The default element to display if this.element is not defined.\n * To be defined in inherited classes.\n *\n * @private\n */\n // eslint-disable-next-line class-methods-use-this\n createDefaultElement() {}\n}\n\nexport default Control;\n","/* eslint-disable class-methods-use-this */\n/* eslint-disable max-classes-per-file */\n\n/**\n * Copyright control interface.\n *\n */\nexport class CopyrightInterface {\n /**\n * Return an array of layer's copyright.\n *\n * @return {String[]} A list of copyrights to render.\n */\n getCopyrights() {}\n}\n\n/**\n * Mixin for CopyrightInterface.\n *\n * @param {Class} Base A class to extend with {CopyrightInterface} functionnalities.\n * @return {Class} A class that implements <CopyrightInterface> class and extends Base;\n * @private\n */\nconst CopyrightMixin = (Base) =>\n class extends Base {\n render() {\n if (!this.element) {\n return;\n }\n this.element.innerHTML = this.active\n ? this.getCopyrights().join(' | ')\n : '';\n }\n\n createDefaultElement() {\n this.element = document.createElement('div');\n this.element.id = 'mbt-copyright';\n Object.assign(this.element.style, {\n position: 'absolute',\n bottom: 0,\n right: 0,\n fontSize: '.8rem',\n padding: '0 10px',\n });\n }\n };\n\nexport default CopyrightMixin;\n","import { inView } from 'ol/layer/Layer';\nimport Control from '../../common/controls/Control';\nimport mixin from '../../common/mixins/CopyrightMixin';\nimport removeDuplicate from '../../common/utils/removeDuplicate';\n\n/**\n * Display layer's copyrights.\n *\n * @example\n * import { Map } from 'ol';\n * import { CopyrightControl } from 'mobility-toolbox-js/ol';\n *\n * const map = new Map({\n * target: 'map',\n * });\n * const control = new CopyrightControl();\n * control.map = map\n *\n *\n * @see <a href=\"/example/ol-copyright\">Openlayers copyright example</a>\n *\n * @extends {Control}\n * @implements {CopyrightInterface}\n */\nclass CopyrightControl extends mixin(Control) {\n constructor(options) {\n super(options);\n this.onPostRender = this.onPostRender.bind(this);\n }\n\n getCopyrights() {\n if (!this.frameState) {\n return [];\n }\n let copyrights = [];\n\n // This code loop comes mainly from ol.\n this.frameState.layerStatesArray.forEach((layerState) => {\n const { layer } = layerState;\n if (\n inView(layerState, this.frameState.viewState) &&\n layer &&\n layer.getSource &&\n layer.getSource() &&\n layer.getSource().getAttributions()\n ) {\n copyrights = copyrights.concat(\n layer.getSource().getAttributions()(this.frameState),\n );\n }\n });\n return removeDuplicate(copyrights);\n }\n\n activate() {\n super.activate();\n if (this.map) {\n this.map.on('postrender', this.onPostRender);\n }\n }\n\n deactivate() {\n if (this.map) {\n this.map.un('postrender', this.onPostRender);\n }\n super.deactivate();\n }\n\n onPostRender(evt) {\n if (this.map && this.element) {\n /**\n * @ignore\n */\n this.frameState = evt.frameState;\n this.render();\n }\n }\n}\n\nexport default CopyrightControl;\n","/* eslint-disable no-empty-function */\n/* eslint-disable no-useless-constructor */\n/* eslint-disable class-methods-use-this */\n/* eslint-disable max-classes-per-file */\nimport StopsAPI from '../../api/stops/StopsAPI';\n\n/**\n * Search control interface.\n *\n * @classproperty {StopsSearchParams} apiParams - Default request parameters used by the search method. See [Stops service documentation](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).\n */\nexport class SearchInterface {\n /**\n * Constructor.\n *\n * @param {Object} options Map options\n * @param {string} options.apiKey Access key for [geOps services](https://developer.geops.io/). See StopsAPI.\n * @param {string} [options.url='https://api.geops.io/tracker/v1'] Stops service url. See StopsAPI.\n * @param {string} [options.placeholder='Search for a stop...'] Input field placeholder.\n * @param {StopsSearchParams} [options.apiParams={ limit: 20 }] Request parameters. See [Stops service documentation](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).\n */\n // eslint-disable-next-line no-unused-vars\n constructor(options = {}) {}\n\n /**\n * Launch a search.\n *\n * @param {String} query The query to search for.\n * @param {AbortController} abortController Abort controller used to cancel the request.\n * @return {Promise<Array<GeoJSONFeature>>} An array of GeoJSON features with coordinates in [EPSG:4326](http://epsg.io/4326).\n */\n // eslint-disable-next-line no-unused-vars\n search(query, abortController) {}\n}\n\n/**\n * Mixin for SearchInterface.\n *\n * @param {Class} Base A class to extend with {SearchInterface} functionnalities.\n * @return {Class} A class that implements <SearchInterface> class and extends Base;\n * @private\n */\nconst SearchMixin = (Base) =>\n class extends Base {\n constructor(options = {}) {\n super(options);\n const { apiParams, apiKey, url } = options;\n\n this.apiParams = { limit: 20, ...(apiParams || {}) };\n this.placeholder = options.placeholder || 'Search for a stop...';\n\n const apiOptions = { apiKey };\n if (url) {\n apiOptions.url = url;\n }\n this.api = new StopsAPI(apiOptions);\n this.abortController = new AbortController();\n }\n\n render(suggestions = []) {\n if (!this.suggestionsElt) {\n return;\n }\n\n this.suggestionsElt.style.display = suggestions.length ? 'block' : 'none';\n\n this.suggestionsElt.innerHTML = '';\n\n suggestions.forEach((suggestion) => {\n const { properties } = suggestion;\n const suggElt = document.createElement('div');\n suggElt.innerHTML = properties.name;\n suggElt.onclick = () => {\n this.onSuggestionClick(suggestion);\n };\n Object.assign(suggElt.style, {\n padding: '5px 12px',\n });\n this.suggestionsElt.appendChild(suggElt);\n });\n }\n\n createDefaultElement() {\n /**\n * Define a default element.\n */\n this.element = document.createElement('div');\n this.element.id = 'mbt-search';\n Object.assign(this.element.style, {\n position: 'absolute',\n top: 0,\n left: '50px',\n margin: '10px',\n display: 'flex',\n flexDirection: 'column',\n width: '320px',\n });\n\n // Create input element\n this.inputElt = document.createElement('input');\n this.inputElt.type = 'text';\n this.inputElt.placeholder = this.placeholder;\n this.inputElt.autoComplete = 'off';\n this.inputElt.onkeyup = (evt) => {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.search(evt.target.value, this.abortController);\n };\n Object.assign(this.inputElt.style, {\n padding: '10px 30px 10px 10px',\n });\n this.element.appendChild(this.inputElt);\n\n // Create suggestions list element\n this.suggestionsElt = document.createElement('div');\n Object.assign(this.suggestionsElt.style, {\n backgroundColor: 'white',\n overflowY: 'auto',\n cursor: 'pointer',\n });\n this.element.appendChild(this.suggestionsElt);\n\n this.clearElt = document.createElement('div');\n Object.assign(this.clearElt.style, {\n display: 'none',\n position: 'absolute',\n right: '0',\n padding: '0 10px',\n fontSize: '200%',\n cursor: 'pointer',\n });\n this.clearElt.innerHTML = '×';\n this.clearElt.onclick = () => this.clear();\n this.element.appendChild(this.clearElt);\n }\n\n search(q, abortController) {\n if (q !== undefined || q !== null) {\n this.apiParams.q = q;\n }\n\n if (this.clearElt) {\n this.clearElt.style.display = 'block';\n }\n\n return this.api\n .search(this.apiParams, abortController)\n .then((data) => {\n this.render(data);\n })\n .catch(() => {\n this.render();\n });\n }\n\n /**\n * To be defined in inherited class\n */\n // eslint-disable-next-line no-unused-vars\n onSuggestionClick(suggestion) {}\n\n /**\n * Clear the search field and close the control.\n */\n clear() {\n if (!this.suggestionsElt) {\n return;\n }\n\n this.inputElt.value = '';\n this.suggestionsElt.innerHTML = '';\n this.clearElt.style.display = 'none';\n }\n };\n\nexport default SearchMixin;\n","import { fromLonLat } from 'ol/proj';\nimport Control from '../../common/controls/Control';\nimport mixin from '../../common/mixins/SearchMixin';\n\n/**\n * Search stations.\n *\n * @example\n * import { Map } from 'ol';\n * import { StopFinderControl } from 'mobility-toolbox-js/ol';\n *\n * const map = new Map({\n * target: 'map',\n * });\n *\n * const control = new StopFinderControl({\n * apiKey: [yourApiKey]\n * });\n *\n * control.map = map;\n *\n *\n * @see <a href=\"/example/ol-search\">Openlayers search example</a>\n *\n * @extends {Control}\n * @implements {SearchInterface}\n */\nclass StopFinderControl extends mixin(Control) {\n /**\n * @private\n */\n onSuggestionClick({ geometry }) {\n const coord = fromLonLat(geometry.coordinates);\n this.map.getView().setCenter(coord);\n }\n}\n\nexport default StopFinderControl;\n","import { getWidth, getHeight } from 'ol/extent';\nimport { fromLonLat } from 'ol/proj';\n\n/**\n * Get the current resolution of a Mapbox map.\n * @param {mapboxgl.Map} map A map object.\n * @private\n */\nexport const getMercatorResolution = (map) => {\n const bounds = map.getBounds().toArray();\n const a = fromLonLat(bounds[0]);\n const b = fromLonLat(bounds[1]);\n const extent = [...a, ...b];\n const { width, height } = map.getCanvas();\n const xResolution = getWidth(extent) / width;\n const yResolution = getHeight(extent) / height;\n return Math.max(xResolution, yResolution);\n};\n\n/**\n * Get the canvas source coordinates of the current map's extent.\n * @param {mapboxgl.Map} map A map object.\n * @private\n */\nexport const getSourceCoordinates = (map, pixelRatio) => {\n // Requesting getBounds is not enough when we rotate the map, so we request manually each corner.\n const { width, height } = map.getCanvas();\n const leftTop = map.unproject({ x: 0, y: 0 });\n const leftBottom = map.unproject({ x: 0, y: height / pixelRatio }); // southWest\n const rightBottom = map.unproject({\n x: width / pixelRatio,\n y: height / pixelRatio,\n });\n const rightTop = map.unproject({ x: width / pixelRatio, y: 0 }); // north east\n return [\n [leftTop.lng, leftTop.lat],\n [rightTop.lng, rightTop.lat],\n [rightBottom.lng, rightBottom.lat],\n [leftBottom.lng, leftBottom.lat],\n ];\n};\n\nexport default {\n getMercatorResolution,\n getSourceCoordinates,\n};\n","import { fromLonLat } from 'ol/proj';\nimport { unByKey } from 'ol/Observable';\nimport { getWidth, getHeight } from 'ol/extent';\nimport transformRotate from '@turf/transform-rotate';\nimport { point } from '@turf/helpers';\nimport mixin from '../../common/mixins/TralisLayerMixin';\nimport Layer from './Layer';\nimport { getSourceCoordinates, getMercatorResolution } from '../utils';\n\n/**\n * Responsible for loading and display data from a Tralis service.\n *\n * @example\n * import { TralisLayer } from 'mobility-toolbox-js/mapbox';\n *\n * const layer = new TralisLayer({\n * url: [yourUrl],\n * apiKey: [yourApiKey],\n * });\n *\n *\n * @see <a href=\"/api/class/src/api/tralis/TralisAPI%20js~TralisAPI%20html\">TralisAPI</a>\n *\n * @extends {Layer}\n * @implements {TralisLayerInterface}\n */\nclass TralisLayer extends mixin(Layer) {\n constructor(options = {}) {\n super({\n ...options,\n });\n\n /** @ignore */\n this.onLoad = this.onLoad.bind(this);\n\n /** @ignore */\n this.onMove = this.onMove.bind(this);\n\n /** @ignore */\n this.onMoveEnd = this.onMoveEnd.bind(this);\n\n /** @ignore */\n this.onZoomEnd = this.onZoomEnd.bind(this);\n\n /** @ignore */\n this.onVisibilityChange = this.onVisibilityChange.bind(this);\n }\n\n /**\n * Initialize the layer.\n *\n * @param {mapboxgl.Map} map A [mapbox Map](https://docs.mapbox.com/mapbox-gl-js/api/map/).\n * @param {string} beforeId Layer's id before which we want to add the new layer.\n * @override\n */\n init(map, beforeId) {\n if (!map) {\n return;\n }\n\n const canvas = map.getCanvas();\n\n super.init(map, {\n width: canvas.width / this.pixelRatio,\n height: canvas.height / this.pixelRatio,\n });\n\n this.source = {\n type: 'canvas',\n canvas: this.tracker.canvas,\n coordinates: getSourceCoordinates(map, this.pixelRatio),\n // Set to true if the canvas source is animated. If the canvas is static, animate should be set to false to improve performance.\n animate: true,\n attribution: this.copyrights && this.copyrights.join(', '),\n };\n\n this.beforeId = beforeId;\n this.layer = {\n id: this.key,\n type: 'raster',\n source: this.key,\n layout: {\n visibility: this.visible ? 'visible' : 'none',\n },\n paint: {\n 'raster-opacity': 1,\n 'raster-fade-duration': 0,\n 'raster-resampling': 'nearest', // important otherwise it looks blurry\n },\n };\n\n if (map.isStyleLoaded()) {\n this.onLoad();\n }\n\n this.map.on('load', this.onLoad);\n\n this.listeners = [this.on('change:visible', this.onVisibilityChange)];\n }\n\n /**\n * Remove listeners from the Mapbox Map.\n */\n terminate() {\n if (this.map) {\n this.map.off('load', this.onLoad);\n\n this.listeners.forEach((listener) => {\n unByKey(listener);\n });\n if (this.map.getLayer(this.key)) {\n this.map.removeLayer(this.key);\n }\n if (this.map.getSource(this.key)) {\n this.map.removeSource(this.key);\n }\n }\n super.terminate();\n }\n\n /**\n * Start updating vehicles position.\n *\n * @listens {mapboxgl.map.event:zoomend} Listen to zoom end event.\n * @listens {mapboxgl.map.event:mousemove} Listen to mousemove end.\n * @override\n */\n start() {\n super.start();\n\n this.map.on('move', this.onMove);\n this.map.on('moveend', this.onMoveEnd);\n this.map.on('zoomend', this.onZoomEnd);\n }\n\n /**\n * Stop updating vehicles position, and unlisten events.\n *\n * @override\n */\n stop() {\n super.stop();\n if (this.map) {\n this.map.off('move', this.onMove);\n this.map.off('moveend', this.onMoveEnd);\n this.map.off('zoomend', this.onZoomEnd);\n }\n }\n\n onLoad() {\n if (!this.map.getSource(this.key)) {\n this.map.addSource(this.key, this.source);\n }\n if (!this.map.getLayer(this.key)) {\n this.map.addLayer(this.layer, this.beforeId);\n }\n }\n\n /**\n * Function triggered when the user click the map.\n * @override\n */\n onUserClickCallback(evt) {\n super.onUserClickCallback({\n coordinate: fromLonLat(evt.lngLat.toArray()),\n ...evt,\n });\n }\n\n /**\n * Function triggered when the user moves the cursor over the map.\n * @override\n */\n onUserMoveCallback(evt) {\n super.onUserMoveCallback({\n coordinate: fromLonLat(evt.lngLat.toArray()),\n ...evt,\n });\n }\n\n /**\n * Render the trajectories using current map's size, resolution and rotation.\n * @param {boolean} noInterpolate if true, renders the vehicles without interpolating theirs positions.\n * @overrides\n */\n renderTrajectories(noInterpolate) {\n const { width, height } = this.map.getCanvas();\n const center = this.map.getCenter();\n\n // We use turf here to have good transform.\n const leftBottom = this.map.unproject({\n x: 0,\n y: height / this.pixelRatio,\n }); // southWest\n const rightTop = this.map.unproject({ x: width / this.pixelRatio, y: 0 }); // north east\n\n const coord0 = transformRotate(\n point([leftBottom.lng, leftBottom.lat]),\n -this.map.getBearing(),\n {\n pivot: [center.lng, center.lat],\n },\n ).geometry.coordinates;\n const coord1 = transformRotate(\n point([rightTop.lng, rightTop.lat]),\n -this.map.getBearing(),\n {\n pivot: [center.lng, center.lat],\n },\n ).geometry.coordinates;\n\n const bounds = [...fromLonLat(coord0), ...fromLonLat(coord1)];\n const xResolution = getWidth(bounds) / (width / this.pixelRatio);\n const yResolution = getHeight(bounds) / (height / this.pixelRatio);\n const res = Math.max(xResolution, yResolution);\n\n // Coordinate of trajectories are in mercator so we have to pass the proper resolution and center in mercator.\n const viewState = {\n size: [width / this.pixelRatio, height / this.pixelRatio],\n center: fromLonLat([center.lng, center.lat]),\n extent: bounds,\n resolution: res,\n zoom: this.map.getZoom(),\n rotation: -(this.map.getBearing() * Math.PI) / 180,\n pixelRatio: this.pixelRatio,\n };\n\n super.renderTrajectories(viewState, noInterpolate);\n }\n\n /**\n * Return the delay in ms before the next rendering.\n */\n getRefreshTimeInMs() {\n return super.getRefreshTimeInMs(this.map.getZoom());\n }\n\n getFeatureInfoAtCoordinate(coordinate, options = {}) {\n const resolution = getMercatorResolution(this.map);\n return super.getFeatureInfoAtCoordinate(coordinate, {\n resolution,\n ...options,\n });\n }\n\n onVisibilityChange() {\n if (this.visible && !this.map.getLayer(this.key)) {\n this.map.addLayer(this.layer, this.beforeId);\n } else if (this.map.getLayer(this.key)) {\n this.map.removeLayer(this.key);\n }\n // We can't use setLayoutProperty it triggers an error probably a bug in mapbox\n // this.map.setLayoutProperty(\n // this.key,\n // 'visibilty',\n // this.visible ? 'visible' : 'none',\n // );\n }\n\n /**\n * Remove the trajectory form the list if necessary.\n *\n * @private\n */\n purgeTrajectory(trajectory, extent, zoom) {\n return super.purgeTrajectory(\n trajectory,\n extent || this.getMercatorExtent(),\n zoom || Math.floor(this.map.getZoom() + 1),\n );\n }\n\n /**\n * Send the current bbox to the websocket\n */\n setBbox(extent, zoom) {\n let newExtent = extent;\n let newZoom = zoom;\n if (!newExtent && this.isUpdateBboxOnMoveEnd) {\n newExtent = extent || this.getMercatorExtent();\n newZoom = Math.floor(this.getOlZoom());\n }\n super.setBbox(newExtent, newZoom);\n }\n\n /**\n * Callback on 'move' event.\n *\n * @private\n */\n onMove() {\n const extent = getSourceCoordinates(this.map, this.pixelRatio);\n const source = this.map.getSource(this.key);\n if (source) {\n source.setCoordinates(extent);\n }\n this.renderTrajectories();\n }\n\n /**\n * Send the new BBOX to the websocket.\n *\n * @param {ol/MapEvent~MapEvent} evt Moveend event\n * @private\n * @override\n */\n onMoveEnd() {\n this.renderTrajectories();\n\n if (this.visible && this.isUpdateBboxOnMoveEnd) {\n this.setBbox();\n }\n }\n\n /**\n * Update the cursor style when hovering a vehicle.\n *\n * @private\n * @override\n */\n onFeatureHover(features, layer, coordinate) {\n super.onFeatureHover(features, layer, coordinate);\n this.map.getCanvasContainer().style.cursor = features.length\n ? 'pointer'\n : 'auto';\n }\n}\n\nexport default TralisLayer;\n","import { unByKey } from 'ol/Observable';\nimport { transformExtent } from 'ol/proj';\nimport LayerCommon from '../../common/layers/Layer';\n\n/**\n * A class representing a layer to display on an OpenLayers map.\n *\n * @example\n * import { Layer } from 'mobility-toolbox-js/ol';\n *\n * const layer = new Layer({\n * olLayer: ...,\n * });\n *\n * @see <a href=\"/example/ol-map\">Map example</a>\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass Layer extends LayerCommon {\n /**\n * Initialize the layer and listen to user events.\n * @param {ol/Map~Map} map\n */\n init(map) {\n super.init(map);\n\n if (!this.map) {\n return;\n }\n\n if (this.isClickActive || this.isHoverActive) {\n this.toggleVisibleListeners();\n this.onChangeVisibleKey = this.on(\n 'change:visible',\n this.toggleVisibleListeners,\n );\n }\n }\n\n terminate(map) {\n if (this.map) {\n this.map.off('mousemove', this.onUserMoveCallback);\n this.map.off('click', this.onUserClickCallback);\n unByKey(this.onChangeVisibleKey);\n }\n super.terminate(map);\n }\n\n /**\n * Function triggered when the user click the map.\n * @private\n */\n onUserClickCallback(evt) {\n super.onUserClickCallback({ coordinate: evt.lngLat.toArray(), ...evt });\n }\n\n /**\n * Function triggered when the user moves the cursor over the map.\n * @private\n */\n onUserMoveCallback(evt) {\n super.onUserMoveCallback({ coordinate: evt.lngLat.toArray(), ...evt });\n }\n\n /**\n * Toggle listeners needed when a layer is avisible or not.\n * @private\n */\n toggleVisibleListeners() {\n if (this.visible) {\n if (this.isClickActive) {\n this.map.on('click', this.onUserClickCallback);\n }\n\n if (this.isHoverActive) {\n this.map.on('mousemove', this.onUserMoveCallback);\n }\n } else {\n if (this.isClickActive) {\n this.map.off('click', this.onUserClickCallback);\n }\n\n if (this.isHoverActive) {\n this.map.off('mousemove', this.onUserMoveCallback);\n }\n }\n }\n\n /**\n * Returns the current extent in mercator coordinates.\n */\n getMercatorExtent() {\n const bounds = this.map.getBounds().toArray();\n return transformExtent(\n [...bounds[0], ...bounds[1]],\n 'EPSG:4326',\n 'EPSG:3857',\n );\n }\n\n /**\n * Returns the equivalent zoom in Openlayers.\n */\n getOlZoom() {\n return this.map.getZoom() + 1;\n }\n\n /**\n * Create a copy of the Layer.\n * @param {Object} newOptions Options to override\n * @return {Layer} A Layer\n */\n clone(newOptions) {\n return new Layer({ ...this.options, ...newOptions });\n }\n}\nexport default Layer;\n","import Control from '../../common/controls/Control';\nimport mixin from '../../common/mixins/CopyrightMixin';\nimport { getMapboxMapCopyrights } from '../../common/utils';\n\n/**\n * Display layer's copyrights.\n *\n * @example\n * import { Map } from 'mapbox-gl';\n * import { CopyrightControl } from 'mobility-toolbox-js/mapbox';\n *\n * const map = new Map({\n * container: 'map',\n * style: `https://maps.geops.io/styles/travic_v2/style.json?key=${window.apiKey}`,\n * controls: [\n * new CopyrightControl()\n * ]\n * });\n *\n * const control = new CopyrightControl();\n * control.map = map;\n *\n *\n * @see <a href=\"/example/mb-copyright\">Mapbox copyright example</a>\n *\n * @extends {Control}\n * @implements {CopyrightInterface}\n */\nclass CopyrightControl extends mixin(Control) {\n constructor(options) {\n super(options);\n this.render = this.render.bind(this);\n }\n\n activate() {\n super.activate();\n if (this.map) {\n this.map.on('sourcedata', this.render);\n this.map.on('styledata', this.render);\n this.map.on('idle', this.render);\n }\n }\n\n deactivate() {\n if (this.map) {\n this.map.off('sourcedata', this.render);\n this.map.off('styledata', this.render);\n this.map.off('idle', this.render);\n }\n super.deactivate();\n }\n\n getCopyrights() {\n return getMapboxMapCopyrights(this.map);\n }\n}\n\nexport default CopyrightControl;\n","import {\n Layer as olLayer,\n WMSLayer as olWMSLayer,\n MapboxLayer as olMapboxLayer,\n TralisLayer as olTralisLayer,\n VectorLayer as olVectorLayer,\n} from './ol';\nimport { TralisLayer as mbTralisLayer } from './mapbox';\n\nconst exports = {\n mapbox: {\n TralisLayer: mbTralisLayer,\n },\n ol: {\n Layer: olLayer,\n WMSLayer: olWMSLayer,\n MapboxLayer: olMapboxLayer,\n TralisLayer: olTralisLayer,\n VectorLayer: olVectorLayer,\n },\n};\n\nexport default exports;\n"],"sourceRoot":""}
1
+ {"version":3,"sources":["webpack://mobility-toolbox-js/webpack/universalModuleDefinition","webpack://mobility-toolbox-js/webpack/bootstrap","webpack://mobility-toolbox-js/external \"ol/proj\"","webpack://mobility-toolbox-js/external \"ol/style\"","webpack://mobility-toolbox-js/external \"ol/Observable\"","webpack://mobility-toolbox-js/external \"ol/geom\"","webpack://mobility-toolbox-js/external \"ol/extent\"","webpack://mobility-toolbox-js/external \"ol/format/GeoJSON\"","webpack://mobility-toolbox-js/external \"query-string\"","webpack://mobility-toolbox-js/external \"ol/source/Source\"","webpack://mobility-toolbox-js/external \"ol/layer/Layer\"","webpack://mobility-toolbox-js/external \"ol/layer\"","webpack://mobility-toolbox-js/external \"ol/transform\"","webpack://mobility-toolbox-js/external \"ol/source\"","webpack://mobility-toolbox-js/external \"ol/Object\"","webpack://mobility-toolbox-js/external \"ol\"","webpack://mobility-toolbox-js/external \"lodash.debounce\"","webpack://mobility-toolbox-js/external \"lodash.throttle\"","webpack://mobility-toolbox-js/external \"ol/geom/GeometryType\"","webpack://mobility-toolbox-js/external \"ol/format\"","webpack://mobility-toolbox-js/external \"@turf/transform-rotate\"","webpack://mobility-toolbox-js/external \"@turf/helpers\"","webpack://mobility-toolbox-js/external \"ol/layer/Group\"","webpack://mobility-toolbox-js/external \"uuid\"","webpack://mobility-toolbox-js/external \"mapbox-gl\"","webpack://mobility-toolbox-js/external \"maplibre-gl\"","webpack://mobility-toolbox-js/external \"ol/math\"","webpack://mobility-toolbox-js/external \"ol/interaction\"","webpack://mobility-toolbox-js/external \"ol/events/condition\"","webpack://mobility-toolbox-js/external \"ol/geom/Point\"","webpack://mobility-toolbox-js/./src/common/layers/Layer.js","webpack://mobility-toolbox-js/./src/ol/layers/Layer.js","webpack://mobility-toolbox-js/./src/common/utils/getMapboxStyleUrl.js","webpack://mobility-toolbox-js/./src/common/utils/removeDuplicate.js","webpack://mobility-toolbox-js/./src/common/utils/getMapboxMapCopyrights.js","webpack://mobility-toolbox-js/./src/common/trackerConfig.js","webpack://mobility-toolbox-js/./src/common/styles/trackerDefaultStyle.js","webpack://mobility-toolbox-js/./src/ol/layers/MapboxLayer.js","webpack://mobility-toolbox-js/./src/ol/layers/RoutingLayer.js","webpack://mobility-toolbox-js/./src/common/utils/getVehiclePosition.js","webpack://mobility-toolbox-js/./src/common/Tracker.js","webpack://mobility-toolbox-js/./src/common/utils/createTrackerFilters.js","webpack://mobility-toolbox-js/./src/common/api/api.js","webpack://mobility-toolbox-js/./src/api/stops/StopsAPI.js","webpack://mobility-toolbox-js/./src/api/tralis/WebSocketConnector.js","webpack://mobility-toolbox-js/./src/api/tralis/TralisAPIUtils.js","webpack://mobility-toolbox-js/./src/api/tralis/TralisAPI.js","webpack://mobility-toolbox-js/./src/common/mixins/TralisLayerMixin.js","webpack://mobility-toolbox-js/./src/ol/styles/fullTrajectoryStyle.js","webpack://mobility-toolbox-js/./src/ol/styles/fullTrajectoryDelayStyle.js","webpack://mobility-toolbox-js/./src/ol/layers/TralisLayer.js","webpack://mobility-toolbox-js/./src/ol/layers/VectorLayer.js","webpack://mobility-toolbox-js/./src/ol/layers/WMSLayer.js","webpack://mobility-toolbox-js/./src/common/controls/Control.js","webpack://mobility-toolbox-js/./src/common/mixins/CopyrightMixin.js","webpack://mobility-toolbox-js/./src/ol/controls/CopyrightControl.js","webpack://mobility-toolbox-js/./src/common/mixins/SearchMixin.js","webpack://mobility-toolbox-js/./src/ol/controls/StopFinderControl.js","webpack://mobility-toolbox-js/./src/mapbox/utils.js","webpack://mobility-toolbox-js/./src/mapbox/layers/TralisLayer.js","webpack://mobility-toolbox-js/./src/mapbox/layers/Layer.js","webpack://mobility-toolbox-js/./src/mapbox/controls/CopyrightControl.js","webpack://mobility-toolbox-js/./src/index.js"],"names":["root","factory","exports","module","define","amd","this","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","require","Layer","options","defineProperties","onClick","onHover","copyrights","onUserClickCallback","onUserMoveCallback","isQueryable","isClickActive","isHoverActive","children","visible","properties","isBaseLayer","hitTolerance","uid","uuid","dfltName","toLowerCase","writable","isMobilityLayer","set","newCopyrights","arrValue","Array","isArray","undefined","map","clickCallbacks","hoverCallbacks","terminate","dispatchEvent","type","target","stopPropagationDown","stopPropagationUp","stopPropagationSiblings","filter","child","find","coordinate","console","error","Promise","resolve","layer","features","callback","Error","includes","push","idx","indexOf","splice","evt","emptyFeatureInfo","event","length","getFeatureInfoAtCoordinate","then","featureInfo","forEach","catch","Observable","olLayer","setVisible","olListenersKeys","addLayer","getLayers","on","element","toggleVisibleListeners","attributions","Group","getArray","getSource","setAttributions","unByKey","removeLayer","isClickListenerKey","isHoverListenerKey","index","newOptions","LayerCommon","getMapboxStyleUrl","apiKey","apiKeyName","styleUrl","parsedStyle","qs","parseUrl","query","stringifyUrl","warn","removeDuplicate","array","arrWithoutEmptyValues","val","trim","lowerCasesValues","str","Set","uniqueStr","getMapboxMapCopyrights","style","sourceCaches","values","sourceCache","used","source","attribution","concat","replace","split","trackerRadiusMapping","0","1","2","3","4","5","6","7","8","9","types","bgColors","textColors","timeSteps","getTypeIndex","findIndex","test","getBgColor","typeIdx","e","getDelayColor","delayInMs","cancelled","isDelayText","createCanvas","width","height","canvas","document","createElement","cacheDelayBg","cacheDelayText","cacheCircle","cacheText","styleCache","trajectory","viewState","hoverVehicleId","selectedVehicleId","useDelayStyle","delayOutlineColor","delayDisplay","zoom","pixelRatio","id","train_id","line","delay","state","operatorProvidesRealtime","operator_provides_realtime_journey","textColor","text_color","color","hover","selected","radius","getRadius","Math","min","floor","isDisplayStrokeAndDelay","mustDrawText","circleFillColor","margin","radiusDelay","markerSize","size","origin","ctx","getContext","delayBg","beginPath","arc","PI","fillStyle","fill","getDelayBgCanvas","drawImage","fontSize","max","text","String","fromCodePoint","rounded","round","getDelayText","delayText","font","delayColor","textAlign","textBaseline","strokeStyle","lineWidth","strokeText","fillText","getDelayTextCanvas","circle","hasStroke","hasDash","setLineDash","stroke","getCircleCanvas","textSize","fillColor","strokeColor","save","restore","getTextCanvas","newText","measureText","getTextSize","getTextColor","MapboxLayer","mbLayer","OLLayer","Source","render","frameState","mbMap","changed","getCanvas","getVisible","renderState","display","position","opacity","getOpacity","rotation","rotateTo","animate","center","jumpTo","toLonLat","getSize","isStyleLoaded","_frame","cancel","_render","err","getContainer","url","updateAttribution","format","GeoJSON","featureProjection","getView","getProjection","loadMbMap","resize","off","triggerRepaint","remove","loaded","getTargetElement","getCenter","x","y","container","Map","createStyleUrl","interactive","trackResize","attributionControl","mapOptions","once","mapboxCanvas","tabIndex","setAttribute","removeAttribute","newAttributions","toString","pixel","project","queryRenderedFeatures","feature","olFeature","readFeature","circleStyle","Circle","Fill","Stroke","Style","image","lineDash","getVehiclePosition","now","noInterpolate","coord","timeIntervals","time_intervals","geometry","olGeometry","getType","GeomType","POINT","getCoordinates","LINE_STRING","intervals","firstInterval","lastInterval","getFirstCoordinate","getLastCoordinate","j","start","startFrac","end","endFrac","geomFrac","getCoordinateAt","Tracker","trajectories","time","Date","resolution","context","clearRect","hoverVehicleImg","hoverVehiclePx","hoverVehicleWidth","hoverVehicleHeight","selectedVehicleImg","selectedVehiclePx","selectedVehicleWidth","selectedVehicleHeight","coordinateToPixelTransform","compose","nbRendered","timeOffset","rotationIcon","px","apply","vehicleImg","imgWidth","imgHeight","nbTrajectoriesRendered","createFilters","route","operator","regexLine","filterList","regexLineList","item","some","regexStr","RegExp","lineList","toUpperCase","linee","lineName","routeList","parseInt","routeId","routeIdentifier","operatorList","op","API","path","params","config","urlParams","clone","keys","fetch","stringify","response","json","data","reject","BaseObject","StopsAPI","abortController","signal","featureCollection","WebSocketConnector","method","reqStr","channel","args","closed","websocket","readyState","CLOSED","closing","CLOSING","connecting","CONNECTING","open","OPEN","messagesOnOpen","subscriptions","subscribed","onOpen","close","WebSocket","subscribePreviousSubscriptions","addEventListener","onclose","message","send","cb","errorCb","unlisten","onMessage","JSON","parse","content","client_reference","onMessageCb","onErrorCb","removeEventListener","getRequestString","listen","quiet","subcr","newSubscr","toRemove","subscr","subscribe","getModeSuffix","modes","SCHEMATIC","compareDepartures","a","b","sortByMinArrivalTime","topStates","aTop","has_fzo","bTop","aDuration","bDuration","min_arrival_time","getTime","cleanStopTime","stations","station","arrivalTimeWithDelay","arrivalTime","departureTime","departureTimeWithDelay","arrivalDelay","TralisModes","RAW","TOPOGRAPHIC","TralisAPI","subscribedStationUic","departureUpdateTimeout","maxDepartureAge","extraGeoms","prefix","opt","projection","bbox","buffer","conn","newUrl","newProjection","newBbox","join","newBuffer","pingIntervalMs","reconnectTimeoutMs","connect","onClose","window","clearInterval","pingInterval","setInterval","clearTimeout","reconnectTimeout","setTimeout","onSuccess","onError","suffix","unsubscribe","depObject","departures","k","sort","future","setMinutes","getMinutes","past","departureArray","platformsBoarding","previousDeparture","platform","to","abs","unshift","stationId","unsubscribeDepartures","departureObject","tDiff","timestamp","timediff","call_id","filterDepartures","uic","stationUpdateTimeout","unsubscribeStations","extraGeom","ref","unsubscribeTrajectory","unsubscribeDeletedVehicles","generalizationLevel","ids","promises","getFullTrajectory","all","unsubscribeFullTrajectory","log","stopSequence","getStopSequence","fullTrajectoryUpdateTimeout","unsubscribeStopSequence","unsubscribeHealthCheck","TralisLayerMixin","Base","debug","api","tenant","minZoomNonTrain","minZoomInterpolation","generalizationLevelByZoom","10","11","12","13","isUpdateBboxOnMoveEnd","throttleRenderTrajectories","throttle","renderTrajectoriesInternal","leading","trailing","debounceRenderTrajectories","debounce","maxWait","onFeatureHover","onFeatureClick","onTrajectoryMessage","onDeleteTrajectoryMessage","onDocumentVisibilityChange","regexPublishedLineName","publishedLineName","tripNumber","speed","live","initTrackerOptions","currSpeed","currTime","isTrackerLayer","trackerDefaultStyle","newSpeed","tracker","newTime","renderTrajectories","renderedTrajectories","devicePixelRatio","useRequestAnimationFrame","useThrottle","useDebounce","newPublishedLineName","updateFilters","newTripNumber","newOperator","newRegex","visibilityRef","stop","startUpdateTime","subscribeTrajectory","subscribeDeletedVehicles","setBbox","stopUpdateTime","updateTimeDelay","getRefreshTimeInMs","updateTimeInterval","iconScale","requestId","cancelAnimationFrame","requestAnimationFrame","extent","purgeTrajectory","roundedZoom","timeStep","nextTick","nextThrottleTick","filterFc","nb","ext","vehicles","containsCoordinate","vehicle","fullTrajectory","bounds","intersects","removeTrajectory","hidden","timeSinceUpdate","time_since_update","rawCoordinates","raw_coordinates","coordinates","fromLonLat","readGeometry","addTrajectory","selectedVehicle","parameters","location","search","publishedName","borderStyle","zIndex","fullTrajectorystyle","lineColor","TralisLayer","layers","VectorLayer","VectorSource","fullTrajectoryStyle","transformContainer","appendChild","top","left","transformOrigin","renderedViewState","renderedCenter","renderedResolution","renderedRotation","pixelCenterRendered","getPixelFromCoordinate","pixelCenter","transform","composeCssTransform","vectorLayer","view","getAnimating","getInteracting","getZoom","currentZoom","onZoomEnd","onMoveEnd","getImageData","calculateExtent","getResolution","getRotation","highlightTrajectory","cursor","clear","newExtent","newZoom","readFeatures","addFeatures","mixin","getFeaturesAtPixel","layerFilter","WMSLayer","AbortController","getFeatureInfoUrl","info_format","query_layers","getParams","abort","resp","Control","active","newActive","activate","deactivate","parentNode","removeChild","targett","createDefaultElement","CopyrightMixin","innerHTML","getCopyrights","assign","bottom","right","padding","getMercatorResolution","getBounds","toArray","xResolution","getWidth","yResolution","getHeight","getSourceCoordinates","leftTop","unproject","leftBottom","rightBottom","rightTop","lng","lat","onLoad","onMove","onVisibilityChange","beforeId","layout","visibility","paint","listeners","listener","getLayer","removeSource","addSource","lngLat","coord0","transformRotate","point","getBearing","pivot","coord1","res","getMercatorExtent","getOlZoom","setCoordinates","getCanvasContainer","onChangeVisibleKey","transformExtent","mapbox","mbTralisLayer","ol","olWMSLayer","olMapboxLayer","olTralisLayer","olVectorLayer"],"mappings":"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","file":"index.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"mobility-toolbox-js\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"mobility-toolbox-js\"] = factory();\n\telse\n\t\troot[\"mobility-toolbox-js\"] = factory();\n})(this, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 27);\n","module.exports = require(\"ol/proj\");","module.exports = require(\"ol/style\");","module.exports = require(\"ol/Observable\");","module.exports = require(\"ol/geom\");","module.exports = require(\"ol/extent\");","module.exports = require(\"ol/format/GeoJSON\");","module.exports = require(\"query-string\");","module.exports = require(\"ol/source/Source\");","module.exports = require(\"ol/layer/Layer\");","module.exports = require(\"ol/layer\");","module.exports = require(\"ol/transform\");","module.exports = require(\"ol/source\");","module.exports = require(\"ol/Object\");","module.exports = require(\"ol\");","module.exports = require(\"lodash.debounce\");","module.exports = require(\"lodash.throttle\");","module.exports = require(\"ol/geom/GeometryType\");","module.exports = require(\"ol/format\");","module.exports = require(\"@turf/transform-rotate\");","module.exports = require(\"@turf/helpers\");","module.exports = require(\"ol/layer/Group\");","module.exports = require(\"uuid\");","module.exports = require(\"mapbox-gl\");","module.exports = require(\"maplibre-gl\");","module.exports = require(\"ol/math\");","module.exports = require(\"ol/interaction\");","module.exports = require(\"ol/events/condition\");","module.exports = require(\"ol/geom/Point\");","import Observable from 'ol/Observable';\nimport { v4 as uuid } from 'uuid';\n\n/**\n * A class representing a layer to display on map.\n *\n * @example\n * const layer = new Layer({\n * name: 'myLayer',\n * });\n *\n * @classproperty {string} name - Name of the layer\n * @classproperty {string} key - Identifier of the layer. Must be unique.\n * @classproperty {string[]} copyrights - Array of copyrights.\n * @classproperty {boolean} isBaseLayer - Define if the layer is a base layer. Read-only.\n * @classproperty {boolean} isQueryable - Define if the layer can be queried. If false, it will set isHoverActive and isClickActive to false. Read-only.\n * @classproperty {boolean} isClickActive - If true feature information will be queried on user click event. See inherited layers for more informations. Read-only.\n * @classproperty {boolean} isHoverActive - If true feature information will be queried on pointer move event. See inherited layers for more informations. Read-only.\n * @classproperty {boolean} isMobilityLayer - Custom property for duck typing since `instanceof` is not working when the instance was created on different bundles. Read-only.\n * @classproperty {Layer[]} children - List of children.\n * @classproperty {boolean} visible - Define if the layer is visible or not.\n * @classproperty {number} hitTolerance - Hit-detection tolerance in css pixels. Pixels inside the radius around the given position will be checked for features.\n * @classproperty {Object} properties - Custom properties.\n * @classproperty {ol/Map~Map|mapboxgl.Map} map - The map where the layer is displayed.\n */\nexport default class Layer extends Observable {\n /**\n * Constructor\n *\n * @param {Object} options\n * @param {string} [options.name=uuid()] Layer name. Default use a generated uuid.\n * @param {string} [options.key=uuid().toLowerCase()] Layer key, will use options.name.toLowerCase() if not specified.\n * @param {string[]} [options.copyrights=undefined] Array of copyrights.\n * @param {Array<Layer>} [options.children=[]] Sublayers.\n * @param {Object} [options.properties={}] Application-specific layer properties.\n * @param {boolean} [options.visible=true] If true this layer is visible on the map.\n * @param {boolean} [options.isBaseLayer=false] If true this layer is a baseLayer.\n * @param {boolean} [options.isQueryable=true] Define if the layer can be queried. If false, it will also set isHoverActive and isClickActive to false. Read-only.\n * @param {boolean} [options.isClickActive=true] If true feature information will be queried on click event. See inherited layers for more informations. Read-only.\n * @param {boolean} [options.isHoverActive=true] If true feature information will be queried on pointer move event. See inherited layers for more informations. Read-only.\n * @param {number} [options.hitTolerance=5] Hit-detection tolerance in css pixels. Pixels inside the radius around the given position will be checked for features.\n */\n constructor(options = {}) {\n super();\n this.defineProperties(options);\n\n // Add mouse event callbacks\n const { onClick, onHover } = options;\n\n if (onHover) {\n this.onHover(onHover);\n }\n\n if (onClick) {\n this.onClick(onClick);\n }\n\n // This if is very important if you remove it you break the copyright control.\n if (options.copyrights) {\n /** @ignore */\n this.copyrights = options.copyrights;\n }\n\n /** @ignore */\n this.onUserClickCallback = this.onUserClickCallback.bind(this);\n\n /** @ignore */\n this.onUserMoveCallback = this.onUserMoveCallback.bind(this);\n }\n\n /**\n * Define layer's properties.\n *\n * @ignore\n */\n defineProperties(options) {\n const {\n name,\n key,\n children,\n visible,\n properties,\n isBaseLayer,\n isQueryable,\n isClickActive,\n isHoverActive,\n hitTolerance,\n } = {\n isQueryable: true,\n isClickActive: true,\n isHoverActive: true,\n ...options,\n };\n const uid = uuid();\n const dfltName = name || uid;\n Object.defineProperties(this, {\n // options is used for clone function.\n options: {\n value: options,\n },\n name: {\n value: dfltName,\n },\n key: {\n value: key || dfltName.toLowerCase(),\n },\n isBaseLayer: {\n value: !!isBaseLayer,\n },\n isQueryable: {\n value: !!isQueryable,\n writable: true,\n },\n isClickActive: {\n value: !!isQueryable && !!isClickActive,\n writable: true,\n },\n isHoverActive: {\n value: !!isQueryable && !!isHoverActive,\n writable: true,\n },\n hitTolerance: {\n value: hitTolerance || 5,\n writable: true,\n },\n // Custom property for duck typing since `instanceof` is not working\n // when the instance was created on different bundles.\n isMobilityLayer: {\n value: true,\n },\n children: {\n value: children || [],\n writable: true,\n },\n copyrights: {\n get: () => this.get('copyrights'),\n set: (newCopyrights) => {\n const arrValue = !Array.isArray(newCopyrights)\n ? [newCopyrights]\n : newCopyrights;\n this.set('copyrights', arrValue);\n },\n },\n visible: {\n value: visible === undefined ? true : visible,\n writable: true,\n },\n properties: {\n value: { ...(properties || {}) },\n },\n map: {\n writable: true,\n },\n /**\n * Callback function when a user click on a feature.\n */\n clickCallbacks: {\n value: [],\n },\n /**\n * Callback function when a user hover on a feature.\n */\n hoverCallbacks: {\n value: [],\n },\n });\n }\n\n /**\n * Initialize the layer with the map passed in parameters.\n *\n * @param {ol/Map~Map|mapboxgl.Map} map A map.\n */\n init(map) {\n this.terminate();\n /** @ignore */\n this.map = map;\n }\n\n /**\n * Terminate what was initialized in init function. Remove layer, events...\n */\n // eslint-disable-next-line class-methods-use-this\n terminate() {}\n\n /**\n * Get a layer property.\n *\n * @param {string} name Property name.\n * @return {property} Property\n */\n get(name) {\n return this.properties[name];\n }\n\n /**\n * Set a layer property.\n *\n * @param {string} name Property name.\n * @param {string} value Value.\n */\n set(name, value) {\n if (value !== this.properties[name]) {\n this.properties[name] = value;\n this.dispatchEvent({\n type: `change:${name}`,\n target: this,\n });\n }\n }\n\n /**\n * Change the visibility of the layer\n *\n * @param {boolean} visible Defines the visibility of the layer\n * @param {boolean} [stopPropagationDown]\n * @param {boolean} [stopPropagationUp]\n * @param {boolean} [stopPropagationSiblings]\n */\n setVisible(\n visible,\n stopPropagationDown = false,\n stopPropagationUp = false,\n stopPropagationSiblings = false,\n ) {\n if (visible === this.visible) {\n return;\n }\n\n /** @ignore */\n this.visible = visible;\n\n this.dispatchEvent({\n type: 'change:visible',\n target: this,\n stopPropagationDown,\n stopPropagationUp,\n stopPropagationSiblings,\n });\n }\n\n /**\n * Returns an array with visible child layers\n *\n * @return {Layer[]} Visible children\n */\n getVisibleChildren() {\n return this.children.filter((child) => child.visible);\n }\n\n /**\n * Checks whether the layer has child layers with visible set to True\n *\n * @return {boolean} True if the layer has visible child layers\n * @deprecated\n */\n hasVisibleChildren() {\n return !!this.children.find((child) => child.visible === true);\n }\n\n /**\n * Request feature information for a given coordinate.\n * This function must be implemented by inheriting layers.\n *\n * @param {ol/coordinate~Coordinate} coordinate Coordinate.\n * @param {Object} options Some options. See child classes to see which are supported.\n * @return {Promise<FeatureInfo>} An empty response.\n */\n // eslint-disable-next-line no-unused-vars\n getFeatureInfoAtCoordinate(coordinate, options) {\n // eslint-disable-next-line no-console\n console.error(\n 'getFeatureInfoAtCoordinate must be implemented by inheriting layers',\n this.key,\n );\n\n // No response so we modify the properties accordingly, to avoid spaming the console.\n this.isQueryable = false;\n // this.isClickActive = false;\n // this.isHoverActive = false;\n\n // This layer returns no feature info.\n // The function is implemented by inheriting layers.\n return Promise.resolve({\n layer: this,\n features: [],\n coordinate,\n });\n }\n\n /**\n * Listens to click events on the layer.\n * @param {function} callback Callback function, called with the clicked\n * features,\n * the layer instance and the click event.\n */\n onClick(callback) {\n if (typeof callback === 'function') {\n if (!this.clickCallbacks.includes(callback)) {\n this.clickCallbacks.push(callback);\n }\n } else {\n throw new Error('onClick callback must be of type function:', callback);\n }\n }\n\n /**\n * Unlistens to click events on the layer.\n * @param {function} callback Callback function, called with the clicked\n * features,\n * the layer instance and the click event.\n */\n unClick(callback) {\n if (typeof callback === 'function') {\n const idx = this.clickCallbacks.indexOf(callback);\n if (idx > -1) {\n this.clickCallbacks.splice(idx, 1);\n }\n }\n }\n\n /**\n * Function triggered when the user click the map.\n * @private\n */\n onUserClickCallback(evt) {\n const emptyFeatureInfo = {\n features: [],\n layer: this,\n coordinate: evt.coordinate,\n event: evt,\n };\n\n if (!this.isClickActive || !this.clickCallbacks.length) {\n return Promise.resolve(emptyFeatureInfo);\n }\n\n return this.getFeatureInfoAtCoordinate(evt.coordinate)\n .then((featureInfo) => {\n const { features, layer, coordinate } = featureInfo;\n this.clickCallbacks.forEach((callback) =>\n callback(features, layer, coordinate),\n );\n return featureInfo;\n })\n .catch(() => emptyFeatureInfo);\n }\n\n /**\n * Listens to hover events on the layer.\n * @param {function} callback Callback function, called with the clicked\n * features, the layer instance and the click event.\n */\n onHover(callback) {\n if (typeof callback === 'function') {\n if (!this.hoverCallbacks.includes(callback)) {\n this.hoverCallbacks.push(callback);\n }\n } else {\n throw new Error('callback must be of type function.');\n }\n }\n\n /**\n * Unlistens to hover events on the layer.\n * @param {function} callback Callback function, called with the hovered\n * features, the layer instance and the click event.\n */\n unHover(callback) {\n if (typeof callback === 'function') {\n const idx = this.hoverCallbacks.indexOf(callback);\n if (idx > -1) {\n this.hoverCallbacks.splice(idx, 1);\n }\n }\n }\n\n /**\n * Function triggered when the user move the cursor.\n * @private\n */\n onUserMoveCallback(evt) {\n const emptyFeatureInfo = {\n features: [],\n layer: this,\n coordinate: evt.coordinate,\n event: evt,\n };\n\n if (!this.isHoverActive || !this.hoverCallbacks.length) {\n return Promise.resolve(emptyFeatureInfo);\n }\n\n return this.getFeatureInfoAtCoordinate(evt.coordinate)\n .then((featureInfo) => {\n const { features, layer, coordinate } = featureInfo;\n this.hoverCallbacks.forEach((callback) =>\n callback(features, layer, coordinate),\n );\n return featureInfo;\n })\n .catch(() => emptyFeatureInfo);\n }\n}\n","import { unByKey } from 'ol/Observable';\nimport Group from 'ol/layer/Group';\nimport LayerCommon from '../../common/layers/Layer';\n\n/**\n * A class representing a layer to display on an OpenLayers map.\n *\n * @example\n * import { Layer } from 'mobility-toolbox-js/ol';\n *\n * const layer = new Layer({\n * olLayer: ...,\n * });\n *\n * @see <a href=\"/example/ol-map\">Map example</a>\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass Layer extends LayerCommon {\n /**\n * Constructor.\n *\n * @param {Object} options\n * @param {ol/layer/Layer~Layer} options.olLayer The layer (required).\n * @param {string} [options.name=uuid()] Layer name. Default use a generated uuid.\n * @param {string} [options.key=uuid().toLowerCase()] Layer key, will use options.name.toLowerCase() if not specified.\n * @param {string} [options.copyright=undefined] Copyright-Statement.\n * @param {Array<Layer>} [options.children=[]] Sublayers.\n * @param {Object} [options.properties={}] Application-specific layer properties.\n * @param {boolean} [options.visible=true] If true this layer is the currently visible layer on the map.\n * @param {boolean} [options.isBaseLayer=false] If true this layer is a baseLayer.\n * @param {boolean} [options.isQueryable=true] If true feature information can be queried by the react-spatial LayerService. Default is true.\n * @param {boolean} [options.isClickActive=true] If true feature information will be queried on 'singleclick' event. All results will be passed to function registered using `onClick` function. Default is true.\n */\n constructor(options) {\n super(options);\n\n if (this.olLayer) {\n this.olLayer.setVisible(this.visible);\n }\n }\n\n /**\n * Define layer's properties.\n *\n * @ignore\n */\n defineProperties(options) {\n super.defineProperties(options);\n Object.defineProperties(this, {\n olLayer: { value: options.olLayer, writable: true },\n olListenersKeys: {\n value: [],\n },\n });\n }\n\n /**\n * Initialize the layer and listen to feature clicks.\n * @param {ol/Map~Map} map\n */\n init(map) {\n super.init(map);\n\n if (!this.map) {\n return;\n }\n\n if (this.map && this.olLayer) {\n this.map.addLayer(this.olLayer);\n }\n\n this.olListenersKeys.push(\n this.map.getLayers().on('remove', (evt) => {\n if (evt.element === this.olLayer) {\n this.terminate();\n }\n }),\n );\n\n if (this.isClickActive || this.isHoverActive) {\n this.toggleVisibleListeners();\n this.olListenersKeys.push(\n this.on('change:visible', this.toggleVisibleListeners),\n );\n }\n\n // We set the copyright to the source used by the layer.\n if (this.copyrights && this.olLayer) {\n const attributions = this.copyrights || [];\n if (this.olLayer instanceof Group) {\n this.olLayer\n .getLayers()\n .getArray()\n .forEach((layer) => {\n layer.getSource().setAttributions(attributions);\n });\n } else if (this.olLayer.getSource) {\n this.olLayer.getSource().setAttributions(attributions);\n }\n }\n }\n\n /**\n * Terminate what was initialized in init function. Remove layer, events...\n */\n terminate() {\n unByKey(this.olListenersKeys);\n\n if (this.map && this.olLayer) {\n this.map.removeLayer(this.olLayer);\n }\n\n super.terminate();\n }\n\n /**\n * Change the visibility of the layer\n *\n * @param {boolean} visible Defines the visibility of the layer\n * @param {boolean} [stopPropagationDown]\n * @param {boolean} [stopPropagationUp]\n * @param {boolean} [stopPropagationSiblings]\n */\n setVisible(\n visible,\n stopPropagationDown = false,\n stopPropagationUp = false,\n stopPropagationSiblings = false,\n ) {\n if (visible === this.visible) {\n return;\n }\n\n super.setVisible(\n visible,\n stopPropagationDown,\n stopPropagationUp,\n stopPropagationSiblings,\n );\n\n if (this.olLayer) {\n this.olLayer.setVisible(this.visible);\n }\n }\n\n /**\n * Toggle listeners needed when a layer is avisible or not.\n * @private\n */\n toggleVisibleListeners() {\n // Remove previous event\n if (this.isClickListenerKey && this.isHoverListenerKey) {\n [this.isClickListenerKey, this.isHoverListenerKey].forEach((key) => {\n const index = this.olListenersKeys.indexOf(key);\n if (index > -1) {\n this.olListenersKeys.splice(index, 1);\n }\n unByKey([this.isHoverListenerKey, this.isClickListenerKey]);\n });\n }\n\n if (this.visible) {\n if (this.isClickActive) {\n this.isClickListenerKey = this.map.on(\n 'singleclick',\n this.onUserClickCallback,\n );\n }\n if (this.isHoverActive) {\n this.isHoverListenerKey = this.map.on(\n 'pointermove',\n this.onUserMoveCallback,\n );\n }\n this.olListenersKeys.push(\n this.isClickListenerKey,\n this.isHoverListenerKey,\n );\n }\n }\n\n /**\n * Create a copy of the Layer.\n * @param {Object} newOptions Options to override\n * @return {Layer} A Layer\n */\n clone(newOptions) {\n return new Layer({ ...this.options, ...newOptions });\n }\n}\nexport default Layer;\n","import qs from 'query-string';\n\n/**\n * Return the styleUrl with apiKey parameters set.\n * @param {string} apiKey apiKey value for the mapbox request.\n * @param {string} apiKeyName parameter name for apiKey in the mapbox request.\n * @param {string} styleUrl mapbox styleUrl value.\n * @ignore\n */\nconst getMapboxStyleUrl = (apiKey, apiKeyName, styleUrl) => {\n if (apiKey === false) {\n return styleUrl;\n }\n const parsedStyle = qs.parseUrl(styleUrl);\n if (!apiKey && parsedStyle.query[apiKeyName]) {\n return styleUrl;\n }\n if (!apiKey) {\n // eslint-disable-next-line no-console\n console.warn(`No apiKey is defined for request to ${styleUrl}`);\n return null;\n }\n return qs.stringifyUrl({\n ...parsedStyle,\n query: {\n ...parsedStyle.query,\n [apiKeyName]: apiKey,\n },\n });\n};\n\nexport default getMapboxStyleUrl;\n","/**\n * This function remove duplicates lower case string value of an array.\n * It removes also null, undefined or non string values.\n *\n * @param {array} array Array of values.\n * @ignore\n */\nconst removeDuplicate = (array) => {\n const arrWithoutEmptyValues = array.filter(\n (val) => val !== undefined && val !== null && val.trim && val.trim(),\n );\n const lowerCasesValues = arrWithoutEmptyValues.map((str) =>\n str.toLowerCase(),\n );\n const uniqueLowerCaseValues = [...new Set(lowerCasesValues)];\n const uniqueValues = uniqueLowerCaseValues.map((uniqueStr) =>\n arrWithoutEmptyValues.find((str) => str.toLowerCase() === uniqueStr),\n );\n return uniqueValues;\n};\n\nexport default removeDuplicate;\n","import removeDuplicate from './removeDuplicate';\n\n/**\n * Return the copyright a Mapbox map.\n * @param {mapboxgl.Map} map A Mapbox map\n * @ignore\n */\nconst getMapboxMapCopyrights = (map) => {\n if (!map || !map.style) {\n return [];\n }\n const { sourceCaches } = map.style;\n let copyrights = [];\n\n Object.values(sourceCaches).forEach((sourceCache) => {\n if (sourceCache.used) {\n const source = sourceCache.getSource();\n const attribution =\n source.attribution || (source.options && source.options.attribution);\n\n if (attribution) {\n copyrights = copyrights.concat(\n attribution.replace(/&copy;/g, '©').split(/(<a.*?<\\/a>)/),\n );\n }\n }\n });\n\n return removeDuplicate(copyrights);\n};\n\nexport default getMapboxMapCopyrights;\n","const trackerRadiusMapping = {\n 0: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 1: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 2: [0, 0, 0, 0, 0, 2, 2, 3, 7, 7, 7, 12, 15, 15, 15, 15, 15],\n 3: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 4: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 5: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 6: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 7: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 8: [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7],\n 9: [0, 0, 0, 0, 0, 2, 2, 3, 7, 7, 7, 12, 15, 15, 15, 15, 15],\n};\n\n/**\n * Trajserv value: 'Tram', 'Subway / Metro / S-Bahn', 'Train', 'Bus', 'Ferry', 'Cable Car', 'Gondola', 'Funicular', 'Long distance bus', 'Rail',\n * New endpoint use Rail instead of Train.\n * New tracker values: null, \"tram\", \"subway\", \"rail\", \"bus\", \"ferry\", \"cablecar\", \"gondola\", \"funicular\", \"coach\".\n *\n * @ignore\n */\nexport const types = [\n /^Tram/i,\n /^Subway( \\/ Metro \\/ S-Bahn)?/i,\n /^Train/i,\n /^Bus/i,\n /^Ferry/i,\n /^Cable ?Car/i,\n /^Gondola/i,\n /^Funicular/i,\n /^(Long distance bus|coach)/i,\n /^Rail/i, // New endpoint use Rail instead of Train.\n];\n\n/**\n * @ignore\n */\nexport const bgColors = [\n '#ffb400',\n '#ff5400',\n '#ff8080',\n '#ea0000',\n '#3000ff',\n '#ffb400',\n '#41a27b',\n '#00d237',\n '#b5b5b5',\n '#ff8080',\n];\n\n/**\n * @ignore\n */\nexport const textColors = [\n '#000000',\n '#ffffff',\n '#000000',\n '#ffffff',\n '#ffffff',\n '#000000',\n '#ffffff',\n '#000000',\n '#000000',\n '#000000',\n];\n\n/**\n * @ignore\n */\nexport const timeSteps = [\n 100000, 50000, 40000, 30000, 20000, 15000, 10000, 5000, 2000, 1000, 400, 300,\n 250, 180, 90, 60, 50, 50, 50, 50, 50,\n];\n\n/**\n * @ignore\n */\nexport const getTypeIndex = (type) => {\n if (typeof type === 'string') {\n return types.findIndex((t) => t.test(type));\n }\n return type;\n};\n\n/**\n * @ignore\n */\nexport const getRadius = (type, zoom) => {\n try {\n const typeIdx = getTypeIndex(type || 0);\n return trackerRadiusMapping[typeIdx][zoom];\n } catch (e) {\n return 1;\n }\n};\n\n/**\n * @ignore\n */\nexport const getBgColor = (type = 0) => {\n try {\n const typeIdx = getTypeIndex(type);\n return bgColors[typeIdx];\n } catch (e) {\n return 1;\n }\n};\n\n/**\n * @ignore\n */\nexport const getTextColor = (type = 0) => {\n try {\n const typeIdx = getTypeIndex(type);\n return textColors[typeIdx];\n } catch (e) {\n return 1;\n }\n};\n\n/**\n * @ignore\n */\nexport const getTextSize = (ctx, markerSize, text, fontSize) => {\n ctx.font = `bold ${fontSize}px Arial`;\n let newText = ctx.measureText(text);\n\n const maxiter = 25;\n let i = 0;\n\n while (newText.width > markerSize - 6 && i < maxiter) {\n // eslint-disable-next-line no-param-reassign\n fontSize -= 0.5;\n ctx.font = `bold ${fontSize}px arial, sans-serif`;\n newText = ctx.measureText(text);\n i += 1;\n }\n return fontSize;\n};\n\n/**\n * @ignore\n * @param {number} delayInMs Delay in milliseconds.\n * @param {boolean} cancelled true if the journey is cancelled.\n * @param {boolean} isDelayText true if the color is used for delay text of the symbol.\n */\nexport const getDelayColor = (delayInMs, cancelled, isDelayText) => {\n if (cancelled) {\n return isDelayText ? '#ff0000' : '#a0a0a0'; // red or gray\n }\n if (delayInMs >= 3600000) {\n return '#ed004c'; // pink { r: 237, g: 0, b: 76, s: '237,0,76' };\n }\n if (delayInMs >= 500000) {\n return '#e80000'; // red { r: 232, g: 0, b: 0, s: '232,0,0' };\n }\n if (delayInMs >= 300000) {\n return '#ff4a00'; // orange { r: 255, g: 74, b: 0, s: '255,74,0' };\n }\n if (delayInMs >= 180000) {\n return '#f7bf00'; // yellow { r: 247, g: 191, b: 0, s: '247,191,0' };\n }\n if (delayInMs === null) {\n return '#a0a0a0'; // grey { r: 160, g: 160, b: 160, s: '160,160,160' };\n }\n return '#00a00c'; // green { r: 0, g: 160, b: 12, s: '0,160,12' };\n};\n\n/**\n * @ignore\n */\nexport const getDelayText = (delayInMs, cancelled) => {\n if (cancelled) {\n return String.fromCodePoint(0x00d7);\n }\n if (delayInMs > 3600000) {\n const rounded = Math.round(delayInMs / 3600000);\n return `+${rounded}h`;\n }\n\n if (delayInMs > 59000) {\n const rounded = Math.round(delayInMs / 60000);\n return `+${rounded}m`;\n }\n\n if (delayInMs > 0) {\n return `+${delayInMs}s`;\n }\n\n return '';\n};\n","import {\n getRadius,\n getBgColor,\n getDelayColor,\n getDelayText,\n getTextColor,\n getTextSize,\n} from '../trackerConfig';\n\nconst createCanvas = (width, height) => {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n};\n\n// Draw circle delay background\nconst cacheDelayBg = {};\nexport const getDelayBgCanvas = (origin, radius, color) => {\n const key = `${origin}, ${radius}, ${color}`;\n if (!cacheDelayBg[key]) {\n const canvas = createCanvas(origin * 2, origin * 2);\n const ctx = canvas.getContext('2d');\n ctx.beginPath();\n ctx.arc(origin, origin, radius, 0, 2 * Math.PI, false);\n ctx.fillStyle = color;\n ctx.filter = 'blur(1px)';\n ctx.fill();\n cacheDelayBg[key] = canvas;\n }\n return cacheDelayBg[key];\n};\n\n// Draw delay text\nconst cacheDelayText = {};\nexport const getDelayTextCanvas = (\n width,\n text,\n fontSize,\n font,\n delayColor,\n delayOutlineColor,\n pixelRatio,\n) => {\n const key = `${width}, ${text}, ${font}, ${delayColor}, ${delayOutlineColor}, ${pixelRatio}`;\n if (!cacheDelayText[key]) {\n const canvas = createCanvas(width, fontSize + 8 * pixelRatio);\n const ctx = canvas.getContext('2d');\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.font = font;\n ctx.fillStyle = delayColor;\n ctx.strokeStyle = delayOutlineColor;\n ctx.lineWidth = 1.5 * pixelRatio;\n const delayText = text;\n ctx.strokeText(delayText, 0, fontSize);\n ctx.fillText(delayText, 0, fontSize);\n cacheDelayText[key] = canvas;\n }\n return cacheDelayText[key];\n};\n\n// Draw colored circle with black border\nconst cacheCircle = {};\nexport const getCircleCanvas = (\n origin,\n radius,\n color,\n hasStroke,\n hasDash,\n pixelRatio,\n) => {\n const key = `${origin}, ${radius}, ${color}, ${hasStroke}, ${hasDash}, ${pixelRatio}`;\n if (!cacheCircle[key]) {\n const canvas = createCanvas(origin * 2, origin * 2);\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = color;\n\n if (hasStroke) {\n ctx.lineWidth = 1 * pixelRatio;\n ctx.strokeStyle = '#000000';\n }\n\n ctx.beginPath();\n ctx.arc(origin, origin, radius, 0, 2 * Math.PI, false);\n ctx.fill();\n\n if (hasDash) {\n ctx.setLineDash([5, 3]);\n }\n\n if (hasStroke) {\n ctx.stroke();\n }\n\n cacheCircle[key] = canvas;\n }\n return cacheCircle[key];\n};\n\n// Draw text in the circle\nconst cacheText = {};\nexport const getTextCanvas = (\n text,\n origin,\n textSize,\n fillColor,\n strokeColor,\n hasStroke,\n pixelRatio,\n) => {\n const key = `${text}, ${origin}, ${textSize}, ${fillColor},${strokeColor}, ${hasStroke}, ${pixelRatio}`;\n if (!cacheText[key]) {\n const canvas = createCanvas(origin * 2, origin * 2);\n const ctx = canvas.getContext('2d');\n\n // Draw a stroke to the text only if a provider provides realtime but we don't use it.\n if (hasStroke) {\n ctx.save();\n ctx.textBaseline = 'middle';\n ctx.textAlign = 'center';\n ctx.font = `bold ${textSize + 2}px Arial`;\n ctx.strokeStyle = strokeColor;\n ctx.strokeText(text, origin, origin);\n ctx.restore();\n }\n\n // Draw a text\n ctx.textBaseline = 'middle';\n ctx.textAlign = 'center';\n ctx.fillStyle = fillColor;\n ctx.font = `bold ${textSize}px Arial`;\n ctx.strokeStyle = strokeColor;\n ctx.strokeText(text, origin, origin);\n ctx.fillText(text, origin, origin);\n\n cacheText[key] = canvas;\n }\n return cacheText[key];\n};\n\n/**\n * A tracker style that take in account the delay.\n *\n * @param {*} trajectory The trajectory to render.\n * @param {*} viewState The view state of the map.\n * @param {*} options Some options to change the rendering\n * @return a canvas\n */\nconst styleCache = {};\nconst style = (trajectory, viewState, options) => {\n const {\n hoverVehicleId,\n selectedVehicleId,\n useDelayStyle,\n delayOutlineColor,\n delayDisplay,\n } = options;\n\n const { zoom, pixelRatio } = viewState;\n let { type, cancelled } = trajectory.properties;\n const {\n train_id: id,\n line,\n delay,\n state,\n operator_provides_realtime_journey: operatorProvidesRealtime,\n } = trajectory.properties;\n let { name, text_color: textColor, color } = line || {};\n\n // In the future, the cancelled property will be removed we still managed it\n // until the backend change is on prod.\n cancelled = cancelled === true || state === 'JOURNEY_CANCELLED';\n\n if (!type) {\n type = 'Rail';\n }\n\n if (!name) {\n name = 'I';\n }\n\n if (!textColor) {\n textColor = '#000000';\n }\n\n if (color && color[0] !== '#') {\n color = `#${color}`;\n }\n\n if (textColor[0] !== '#') {\n textColor = `#${textColor}`;\n }\n\n const z = Math.min(Math.floor(zoom || 1), 16);\n const hover = hoverVehicleId && hoverVehicleId === id;\n const selected = selectedVehicleId && selectedVehicleId === id;\n\n // Calcul the radius of the circle\n let radius = getRadius(type, z) * pixelRatio;\n const isDisplayStrokeAndDelay = radius >= 7 * pixelRatio;\n if (hover || selected) {\n radius = isDisplayStrokeAndDelay\n ? radius + 5 * pixelRatio\n : 14 * pixelRatio;\n }\n const mustDrawText = radius > 10 * pixelRatio;\n\n // Optimize the cache key, very important in high zoom level\n let key = `${radius}${type}${color}${hover}${selected}${cancelled}${delay}`;\n\n if (useDelayStyle) {\n key += `${operatorProvidesRealtime}`;\n }\n\n if (mustDrawText) {\n key += `${name}${textColor}`;\n }\n\n if (!styleCache[key]) {\n if (radius === 0) {\n styleCache[key] = null;\n return null;\n }\n\n const margin = 1 * pixelRatio;\n const radiusDelay = radius + 2;\n const markerSize = radius * 2;\n const size = radiusDelay * 2 + margin * 2 + 100 * pixelRatio; // add space for delay information\n const origin = size / 2;\n\n // Create the canvas\n const canvas = createCanvas(size, size);\n const ctx = canvas.getContext('2d');\n\n if (isDisplayStrokeAndDelay && delay !== null) {\n // Draw circle delay background\n const delayBg = getDelayBgCanvas(\n origin,\n radiusDelay,\n getDelayColor(delay, cancelled),\n );\n ctx.drawImage(delayBg, 0, 0);\n }\n\n // Show delay if feature is hovered or if delay is above 5mins.\n if (\n isDisplayStrokeAndDelay &&\n (hover || delay >= delayDisplay || cancelled)\n ) {\n // Draw delay text\n const fontSize =\n Math.max(\n cancelled ? 19 : 14,\n Math.min(cancelled ? 19 : 17, radius * 1.2),\n ) * pixelRatio;\n const text = getDelayText(delay, cancelled);\n\n if (text) {\n const textWidth = text.length * fontSize;\n const delayText = getDelayTextCanvas(\n textWidth,\n text,\n fontSize,\n `bold ${fontSize}px arial, sans-serif`,\n getDelayColor(delay, cancelled, true),\n delayOutlineColor,\n pixelRatio,\n );\n ctx.drawImage(\n delayText,\n origin + radiusDelay + margin,\n origin - fontSize,\n );\n }\n }\n\n // Draw colored circle with black border\n let circleFillColor;\n if (useDelayStyle) {\n circleFillColor = getDelayColor(delay, cancelled);\n } else {\n circleFillColor = color || getBgColor(type);\n }\n\n const hasStroke = isDisplayStrokeAndDelay || hover || selected;\n\n const hasDash =\n isDisplayStrokeAndDelay &&\n useDelayStyle &&\n delay === null &&\n operatorProvidesRealtime === 'yes';\n\n const circle = getCircleCanvas(\n origin,\n radius,\n circleFillColor,\n hasStroke,\n hasDash,\n pixelRatio,\n );\n\n ctx.drawImage(circle, 0, 0);\n\n // Draw text in the circle\n if (mustDrawText) {\n const fontSize = Math.max(radius, 10);\n const textSize = getTextSize(ctx, markerSize, name, fontSize);\n const textColor2 = !useDelayStyle\n ? textColor || getTextColor(type)\n : '#000000';\n const hasStroke2 =\n useDelayStyle && delay === null && operatorProvidesRealtime === 'yes';\n\n const text = getTextCanvas(\n name,\n origin,\n textSize,\n textColor2,\n circleFillColor,\n hasStroke2,\n pixelRatio,\n );\n\n ctx.drawImage(text, 0, 0);\n }\n\n styleCache[key] = canvas;\n }\n\n return styleCache[key];\n};\nexport default style;\n","/* eslint-disable no-underscore-dangle */\nimport { toLonLat } from 'ol/proj';\nimport { Map } from 'mapbox-gl';\nimport Source from 'ol/source/Source';\nimport OLLayer from 'ol/layer/Layer';\nimport GeoJSON from 'ol/format/GeoJSON';\nimport Layer from './Layer';\nimport { getMapboxMapCopyrights, getMapboxStyleUrl } from '../../common/utils';\n\n/**\n * A class representing Mapboxlayer to display on BasicMap\n *\n * @example\n * import { MapboxLayer } from 'mobility-toolbox-js/ol';\n *\n * const layer = new MapboxLayer({\n * url: 'https://maps.geops.io/styles/travic_v2/style.json',\n * apikey: 'yourApiKey',\n * });\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nexport default class MapboxLayer extends Layer {\n /**\n * Constructor.\n *\n * @param {Object} options\n * @param {boolean} [options.preserveDrawingBuffer=false] If true able to export the canvas.\n * @param {number} [options.fadeDuration=300] Duration of the fade effect in ms.\n */\n constructor(options = {}) {\n const mbLayer = new OLLayer({\n source: new Source({}),\n render: (frameState) => {\n if (!this.mbMap) {\n // eslint-disable-next-line no-console\n console.warn(\"Mapbox map doesn't exist.\");\n return null;\n }\n let changed = false;\n const canvas = this.mbMap.getCanvas();\n const { viewState } = frameState;\n\n const visible = this.olLayer.getVisible();\n if (this.renderState.visible !== visible) {\n canvas.style.display = visible ? 'block' : 'none';\n this.renderState.visible = visible;\n // Needed since mapbox-gl 1.9.0.\n // Without you don't see others ol layers on top.\n canvas.style.position = 'absolute';\n }\n\n const opacity = this.olLayer.getOpacity();\n if (this.renderState.opacity !== opacity) {\n canvas.style.opacity = opacity;\n this.renderState.opacity = opacity;\n }\n\n // adjust view parameters in mapbox\n const { rotation } = viewState;\n if (this.renderState.rotation !== rotation) {\n this.mbMap.rotateTo((-(rotation || 0) * 180) / Math.PI, {\n animate: false,\n });\n changed = true;\n this.renderState.rotation = rotation;\n }\n\n if (\n this.renderState.zoom !== viewState.zoom ||\n this.renderState.center[0] !== viewState.center[0] ||\n this.renderState.center[1] !== viewState.center[1]\n ) {\n this.mbMap.jumpTo({\n center: toLonLat(viewState.center),\n zoom: viewState.zoom - 1,\n animate: false,\n });\n changed = true;\n this.renderState.zoom = viewState.zoom;\n this.renderState.center = viewState.center;\n }\n\n const size = this.map.getSize();\n if (\n this.renderState.size[0] !== size[0] ||\n this.renderState.size[1] !== size[1]\n ) {\n changed = true;\n this.renderState.size = size;\n }\n\n // cancel the scheduled update & trigger synchronous redraw\n // see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184\n // NOTE: THIS MIGHT BREAK WHEN UPDATING MAPBOX\n if (\n this.mbMap &&\n this.mbMap.style &&\n this.mbMap.isStyleLoaded() &&\n changed\n ) {\n try {\n if (this.mbMap._frame) {\n this.mbMap._frame.cancel();\n this.mbMap._frame = null;\n }\n this.mbMap._render();\n } catch (err) {\n // ignore render errors because it's probably related to\n // a render during an update of the style.\n // eslint-disable-next-line no-console\n console.warn(err);\n }\n }\n\n return this.mbMap.getContainer();\n },\n });\n\n super({\n ...options,\n olLayer: mbLayer,\n });\n\n /**\n * Url of the mapbox style.\n * @type {string}\n * @private\n */\n this.styleUrl = options.url;\n\n /**\n * Api key for the url of the mapbox style.\n * If set to false, the apiKey is not required.\n * @type {string}\n * @private\n */\n this.apiKey = options.apiKey;\n\n /**\n * Name of the apiKey to set in the url request.\n * Default is 'key'.\n * @type {string}\n * @private\n */\n this.apiKeyName = options.apiKeyName || 'key';\n\n /** @ignore */\n this.updateAttribution = this.updateAttribution.bind(this);\n }\n\n /**\n * Initialize the layer and listen to feature clicks.\n * @param {ol/Map~Map} map\n */\n init(map) {\n super.init(map);\n\n if (!this.map || this.mbMap) {\n return;\n }\n\n /**\n * The feature format.\n * @type {ol/format/GeoJSON}\n */\n this.format = new GeoJSON({\n featureProjection: this.map.getView().getProjection(),\n });\n\n this.loadMbMap();\n\n this.olListenersKeys.push(\n this.map.on('change:size', () => {\n try {\n if (this.mbMap) {\n this.mbMap.resize();\n }\n } catch (err) {\n // ignore render errors\n // eslint-disable-next-line no-console\n console.warn(err);\n }\n }),\n );\n }\n\n /**\n * Terminate what was initialized in init function. Remove layer, events...\n */\n terminate() {\n if (this.mbMap) {\n this.mbMap.off('idle', this.updateAttribution);\n // Some asynchrone repaints are triggered even if the mbMap has been removed,\n // to avoid display of errors we set an empty function.\n this.mbMap.triggerRepaint = () => {};\n this.mbMap.remove();\n this.mbMap = null;\n }\n this.loaded = false;\n super.terminate();\n }\n\n /**\n * Returns a style URL with apiKey & apiKeyName infos.\n * @private\n */\n createStyleUrl() {\n return getMapboxStyleUrl(this.apiKey, this.apiKeyName, this.styleUrl);\n }\n\n /**\n * Create the mapbox map.\n * @private\n */\n loadMbMap() {\n this.olListenersKeys.push(\n this.map.on('change:target', () => {\n this.loadMbMap();\n }),\n );\n\n if (!this.map.getTargetElement()) {\n return;\n }\n\n if (!this.visible) {\n // On next change of visibility we load the map\n this.olListenersKeys.push(\n this.once('change:visible', () => {\n this.loadMbMap();\n }),\n );\n return;\n }\n\n // If the map hasn't been resized, the center could be [NaN,NaN].\n // We set default good value for the mapbox map, to avoid the app crashes.\n let [x, y] = this.map.getView().getCenter();\n if (!x || !y) {\n x = 0;\n y = 0;\n }\n\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.width = '100%';\n container.style.height = '100%';\n\n /**\n * A mapbox map\n * @type {mapboxgl.Map}\n */\n this.mbMap = new Map({\n style: this.createStyleUrl(),\n container,\n interactive: false,\n trackResize: false,\n attributionControl: false,\n ...(this.options.mapOptions || {}),\n });\n\n // Options the last render run did happen. If something changes\n // we have to render again\n /** @ignore */\n this.renderState = {\n center: [x, y],\n zoom: null,\n rotation: null,\n visible: null,\n opacity: null,\n size: [0, 0],\n };\n\n this.mbMap.once('load', () => {\n this.mbMap.resize();\n /**\n * Is the map loaded.\n * @type {boolean}\n */\n this.loaded = true;\n\n /** @ignore */\n this.copyrights = getMapboxMapCopyrights(this.mbMap) || [];\n\n this.olLayer.getSource().setAttributions(this.copyrights);\n\n this.dispatchEvent({\n type: 'load',\n target: this,\n });\n });\n\n const mapboxCanvas = this.mbMap.getCanvas();\n if (mapboxCanvas) {\n if (this.options.tabIndex) {\n mapboxCanvas.setAttribute('tabindex', this.options.tabIndex);\n } else {\n // With a tabIndex='-1' the mouse events works but the map is not focused when we click on it\n // so we remove completely the tabIndex attribute.\n mapboxCanvas.removeAttribute('tabindex');\n }\n }\n\n this.mbMap.on('idle', this.updateAttribution);\n }\n\n /**\n * Update attributions of the source.\n * @private\n */\n updateAttribution(evt) {\n const newAttributions = getMapboxMapCopyrights(evt.target) || [];\n if (this.copyrights.toString() !== newAttributions.toString()) {\n this.copyrights = newAttributions;\n this.olLayer.getSource().setAttributions(newAttributions);\n }\n }\n\n /**\n * Request feature information for a given coordinate.\n * @param {ol/coordinate~Coordinate} coordinate Coordinate to request the information at.\n * @param {Object} options A [mapboxgl.Map#queryrenderedfeatures](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures) options parameter.\n * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate. The original Mapbox feature is available as a property named 'mapboxFeature'.\n */\n getFeatureInfoAtCoordinate(coordinate, options) {\n // Ignore the getFeatureInfo until the mapbox map is loaded\n if (\n !options ||\n !this.format ||\n !this.mbMap ||\n !this.mbMap.isStyleLoaded()\n ) {\n return Promise.resolve({ coordinate, features: [], layer: this });\n }\n\n let pixel = coordinate && this.mbMap.project(toLonLat(coordinate));\n\n if (this.hitTolerance) {\n const { x, y } = pixel;\n pixel = [\n { x: x - this.hitTolerance, y: y - this.hitTolerance },\n { x: x + this.hitTolerance, y: y + this.hitTolerance },\n ];\n }\n\n // At this point we get GeoJSON Mapbox feature, we transform it to an OpenLayers\n // feature to be consistent with other layers.\n const features = this.mbMap\n .queryRenderedFeatures(pixel, options)\n .map((feature) => {\n const olFeature = this.format.readFeature(feature);\n if (olFeature) {\n // We save the original mapbox feature to avoid losing informations\n // potentially needed for other functionnality like highlighting\n // (id, layer id, source, sourceLayer ...)\n olFeature.set('mapboxFeature', feature);\n }\n return olFeature;\n });\n\n return Promise.resolve({\n layer: this,\n features,\n coordinate,\n });\n }\n\n /**\n * Create a copy of the MapboxLayer.\n * @param {Object} newOptions Options to override\n * @return {MapboxLayer} A MapboxLayer\n */\n clone(newOptions) {\n return new MapboxLayer({ ...this.options, ...newOptions });\n }\n}\n","import { Circle, Fill, Stroke, Style } from 'ol/style';\nimport { Vector as VectorSource } from 'ol/source';\nimport { Vector } from 'ol/layer';\nimport Layer from './Layer';\n\nconst circleStyle = new Circle({\n radius: 6,\n fill: new Fill({\n color: [255, 0, 0, 1],\n }),\n stroke: new Stroke({\n color: [0, 0, 0, 1],\n width: 1,\n }),\n});\n\nconst blackBorder = new Style({\n stroke: new Stroke({\n color: [0, 0, 0, 1],\n width: 5,\n }),\n});\n\nconst redLine = new Style({\n image: circleStyle,\n stroke: new Stroke({\n color: [255, 0, 0, 1],\n width: 3,\n }),\n});\n\nconst dashedRedLine = new Style({\n image: circleStyle,\n stroke: new Stroke({\n color: [255, 0, 0, 1],\n width: 3,\n lineDash: [1, 10],\n }),\n});\n\nconst defaultStyleFunction = (feature, resolution) => {\n const minResolution = feature.get('minResolution');\n const maxResolution = feature.get('maxResolution');\n const inRange = resolution <= minResolution && resolution > maxResolution;\n\n if (minResolution && maxResolution && !inRange) {\n return null;\n }\n const mot = feature.get('mot');\n\n if (mot !== 'foot') {\n return [blackBorder, redLine];\n }\n\n return [dashedRedLine];\n};\n\n/**\n * A class use to display vector data.\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass RoutingLayer extends Layer {\n /**\n * Constructor.\n * @param {Object} [options]\n * @param {ol/style/Style~StyleLike} [options.style] Style to be used for routes, uses (ol/StyleLike) [https://openlayers.org/en/latest/apidoc/module-ol_style_Style.html#~StyleLike] instances\n */\n constructor(options = {}) {\n super(options);\n\n this.olLayer =\n options.olLayer ||\n new Vector({\n source: new VectorSource(),\n style: options.style || defaultStyleFunction,\n });\n }\n\n /**\n * Create a copy of the RoutingLayer.\n * @param {Object} newOptions Options to override\n * @return {RoutingLayer} A RoutingLayer\n */\n clone(newOptions) {\n return new RoutingLayer({ ...this.options, ...newOptions });\n }\n}\n\nexport default RoutingLayer;\n","import GeomType from 'ol/geom/GeometryType';\n\n/**\n * Interpolate or not the vehicle position from a trajectory at a specific date.\n *\n * @param {number} now Current date to interpolate a position with. In ms.\n * @param {TralisTrajectory} trajectory The trajectory to interpolate.\n * @param {boolean} noInterpolate If true, the vehicle position is not interpolated on each render but only once.\n * @returns\n */\nconst getVehiclePosition = (now, trajectory, noInterpolate) => {\n const {\n time_intervals: timeIntervals,\n olGeometry: geometry,\n coordinate,\n } = trajectory.properties;\n\n let coord;\n let rotation;\n\n if (noInterpolate && coordinate) {\n coord = coordinate;\n } else if (geometry.getType() === GeomType.POINT) {\n coord = geometry.getCoordinates();\n } else if (geometry.getType() === GeomType.LINE_STRING) {\n const intervals = timeIntervals || [[]];\n const firstInterval = intervals[0];\n const lastInterval = intervals[intervals.length - 1];\n\n // Between the last time interval of a trajectory event and the beginning\n // of the new trajectory event, there is few seconds, can be 6 to 30\n // seconds (that's why the vehicle jumps sometimes).\n // So we make the choice here to display the last (or the first) position\n // of an trajectory event instead of removing them, if the current date is\n // outside the time intervals we display the vehicle at the last (or first) position known.\n if (now < firstInterval[0]) {\n // Display first position known.\n [, , rotation] = firstInterval;\n coord = geometry.getFirstCoordinate();\n } else if (now > lastInterval[0]) {\n // Display last position known.\n [, , rotation] = lastInterval;\n coord = geometry.getLastCoordinate();\n } else {\n // Interpolate position using time intervals.\n for (let j = 0; j < intervals.length - 1; j += 1) {\n // Rotation only available in tralis layer.\n const [start, startFrac] = intervals[j];\n const [end, endFrac] = intervals[j + 1];\n\n if (start <= now && now <= end) {\n // interpolate position inside the time interval.\n const timeFrac = Math.min((now - start) / (end - start), 1);\n const geomFrac = timeFrac * (endFrac - startFrac) + startFrac;\n coord = geometry.getCoordinateAt(geomFrac);\n [, , rotation] = intervals[j];\n break;\n }\n }\n }\n } else {\n // eslint-disable-next-line no-console\n console.error(\n 'This geometry type is not supported. Only Point or LineString are. Current geometry: ',\n geometry,\n );\n }\n\n return { coord, rotation };\n};\n\nexport default getVehiclePosition;\n","/* eslint-disable no-param-reassign */\nimport { compose, apply, create } from 'ol/transform';\nimport getVehiclePosition from './utils/getVehiclePosition';\n\n/**\n * Tracker. This class stores and allows to draw trajectories on a canvas.\n * @class\n * @param {Object} options\n * @private\n */\nexport default class Tracker {\n /**\n * @private\n */\n constructor(options) {\n /**\n * Function use to style the features displayed.\n * @type {function}\n */\n this.style = options.style;\n\n // we draw directly on the canvas since openlayers is too slow.\n /**\n * HTML <canvas> element.\n * @type {Canvas}\n */\n this.canvas = options.canvas || document.createElement('canvas');\n }\n\n /**\n * Draw all the trajectories available to the canvas.\n * @param {ViewState} trajectories An array of trajectories.\n * @param {ViewState} viewState The view state of the map.\n * @param {boolean} options.hoverVehicleId The id of the vehicle to highlight.\n * @param {boolean} options.selectedVehicleId The id of the vehicle to select.\n * @param {boolean} options.noInterpolate If true trajectories are not interpolated but\n * drawn at the last known coordinate. Use this for performance optimization\n * during map navigation.\n * @private\n */\n renderTrajectories(trajectories, viewState, options) {\n const {\n time = Date.now(),\n size = [],\n center,\n resolution,\n rotation = 0,\n pixelRatio,\n } = viewState;\n const {\n noInterpolate = false,\n hoverVehicleId,\n selectedVehicleId,\n } = options;\n\n const { canvas } = this;\n const context = canvas.getContext('2d');\n context.clearRect(0, 0, canvas.width, canvas.height);\n\n const [width, height] = size;\n if (\n width &&\n height &&\n (canvas.width !== width || canvas.height !== height)\n ) {\n [canvas.width, canvas.height] = [width * pixelRatio, height * pixelRatio];\n }\n\n const coordinateToPixelTransform = compose(\n create(),\n size[0] / 2,\n size[1] / 2,\n 1 / resolution,\n -1 / resolution,\n -rotation,\n -center[0],\n -center[1],\n );\n\n // Offscreen canvas has not style attribute\n if (canvas.style) {\n canvas.style.width = `${canvas.width / pixelRatio}px`;\n canvas.style.height = `${canvas.height / pixelRatio}px`;\n }\n\n let hoverVehicleImg;\n let hoverVehiclePx;\n let hoverVehicleWidth;\n let hoverVehicleHeight;\n let selectedVehicleImg;\n let selectedVehiclePx;\n let selectedVehicleWidth;\n let selectedVehicleHeight;\n let nbRendered = 0;\n\n for (let i = trajectories.length - 1; i >= 0; i -= 1) {\n const trajectory = trajectories[i];\n\n // We simplify the trajectory object\n const { train_id: id, timeOffset } = trajectory.properties;\n // We set the rotation and the timeFraction of the trajectory (used by tralis).\n // if rotation === null that seems there is no rotation available.\n const { coord, rotation: rotationIcon } = getVehiclePosition(\n time - (timeOffset || 0),\n trajectory,\n noInterpolate,\n );\n\n // We store the current vehicle position to the trajectory.\n trajectories[i].properties.coordinate = coord;\n trajectories[i].properties.rotation = rotationIcon;\n\n if (!coord) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n let px = apply(coordinateToPixelTransform, [...coord]);\n if (!px) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n px = px.map((p) => p * pixelRatio);\n\n if (\n px[0] < 0 ||\n px[0] > canvas.width ||\n px[1] < 0 ||\n px[1] > canvas.height\n ) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n const vehicleImg = this.style(trajectory, viewState, options);\n if (!vehicleImg) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n nbRendered += 1;\n\n const imgWidth = vehicleImg.width;\n const imgHeight = vehicleImg.height;\n\n if (hoverVehicleId !== id && selectedVehicleId !== id) {\n context.drawImage(\n vehicleImg,\n px[0] - imgWidth / 2,\n px[1] - imgHeight / 2,\n imgWidth,\n imgHeight,\n );\n }\n\n if (hoverVehicleId && hoverVehicleId === id) {\n // Store the canvas to draw it at the end\n hoverVehicleImg = vehicleImg;\n hoverVehiclePx = px;\n hoverVehicleWidth = imgWidth;\n hoverVehicleHeight = imgHeight;\n }\n\n if (selectedVehicleId && selectedVehicleId === id) {\n // Store the canvas to draw it at the end\n selectedVehicleImg = vehicleImg;\n selectedVehiclePx = px;\n selectedVehicleWidth = imgWidth;\n selectedVehicleHeight = imgHeight;\n }\n }\n\n if (selectedVehicleImg) {\n context.drawImage(\n selectedVehicleImg,\n selectedVehiclePx[0] - selectedVehicleWidth / 2,\n selectedVehiclePx[1] - selectedVehicleHeight / 2,\n selectedVehicleWidth,\n selectedVehicleHeight,\n );\n }\n\n if (hoverVehicleImg) {\n context.drawImage(\n hoverVehicleImg,\n hoverVehiclePx[0] - hoverVehicleWidth / 2,\n hoverVehiclePx[1] - hoverVehicleHeight / 2,\n hoverVehicleWidth,\n hoverVehicleHeight,\n );\n }\n return {\n nbTrajectoriesRendered: nbRendered,\n };\n }\n}\n","/**\n * Return a filter functions based on some parameters of a vehicle.\n *\n * @param {string|Array<string>} line - A list of vehicle's name to filter. Names can be separated by a comma. Ex: 'S1,S2,S3'\n * @param {string|Array<string} route - A list of vehicle's route (contained in routeIdentifier property) to filter. Indentifiers can be separated by a comma. Ex: 'id1,id2,id3'\n * @param {string|Array<string} operator A list of vehicle's operator to filter. Operators can be separated by a comma. Ex: 'SBB,DB'\n * @param {Regexp} regexLine - A regex aplly of vehcile's name.\n * @private\n */\nconst createFilters = (line, route, operator, regexLine) => {\n const filterList = [];\n\n if (!line && !route && !operator && !regexLine) {\n return null;\n }\n\n if (regexLine) {\n const regexLineList =\n typeof regexLine === 'string' ? [regexLine] : regexLine;\n const lineFilter = (item) => {\n const name =\n item.properties.name ||\n (item.properties.line && item.properties.line.name) ||\n '';\n if (!name) {\n return false;\n }\n return regexLineList.some((regexStr) =>\n new RegExp(regexStr, 'i').test(name),\n );\n };\n filterList.push(lineFilter);\n }\n\n if (line) {\n const lineFiltersList = typeof line === 'string' ? line.split(',') : line;\n const lineList = lineFiltersList.map((l) =>\n l.replace(/\\s+/g, '').toUpperCase(),\n );\n const lineFilter = (item) => {\n const { line: linee, name } = item.properties;\n const lineName = (name || (linee && linee.name) || '').toUpperCase();\n if (!lineName) {\n return false;\n }\n return lineList.includes(lineName);\n };\n filterList.push(lineFilter);\n }\n\n if (route) {\n const routes = typeof route === 'string' ? route.split(',') : route;\n const routeList = routes.map((item) => parseInt(item, 10));\n const routeFilter = (item) => {\n const routeId = parseInt(\n item.properties.routeIdentifier.split('.')[0],\n 10,\n );\n return routeList.includes(routeId);\n };\n filterList.push(routeFilter);\n }\n\n if (operator) {\n const operatorList = typeof operator === 'string' ? [operator] : operator;\n const operatorFilter = (item) =>\n operatorList.some((op) =>\n new RegExp(op, 'i').test(item.properties.operator),\n );\n filterList.push(operatorFilter);\n }\n\n if (!filterList.length) {\n return null;\n }\n\n return (t) => {\n for (let i = 0; i < filterList.length; i += 1) {\n if (!filterList[i](t)) {\n return false;\n }\n }\n return true;\n };\n};\n\nexport default createFilters;\n","import qs from 'query-string';\nimport BaseObject from 'ol/Object';\n\n/**\n * Common class to access to a geOps api.\n *\n * @example\n * import { API } from 'mobility-toolbox-js/api';\n *\n * const api = new API({\n * url: [yourUrl],\n * apiKey: [yourApiKey]\n * });\n *\n * @classproperty {string} url Url of the service.\n * @classproperty {string} apiKey Api key to access the service.\n */\nclass API extends BaseObject {\n constructor(options = {}) {\n super();\n /** @ignore */\n this.url = options.url;\n\n /** @ignore */\n this.apiKey = options.apiKey;\n }\n\n /**\n * Append the apiKey before sending the request.\n * @ignore\n */\n fetch(path, params, config) {\n // Clean requets parameters, removing undefined and null values.\n const urlParams = { ...(params || {}), key: this.apiKey };\n const clone = { ...urlParams };\n Object.keys(urlParams).forEach(\n (key) =>\n (clone[key] === undefined || clone[key] === null) && delete clone[key],\n );\n if (!this.apiKey) {\n // eslint-disable-next-line no-console\n return Promise.reject(\n new Error(`No apiKey defined for request to ${this.url}`),\n );\n }\n return fetch(\n `${this.url}${path || ''}?${qs.stringify(clone)}`,\n config,\n ).then((response) => {\n try {\n return response.json().then((data) => {\n if (data.error) {\n throw new Error(data.error);\n }\n return data;\n });\n } catch (err) {\n return Promise.reject(new Error(err));\n }\n });\n }\n}\n\nexport default API;\n","import API from '../../common/api/api';\n\n/**\n * Access to the [Stops service](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).\n *\n * @example\n * import { StopsAPI } from 'mobility-toolbox-js/api';\n *\n * const api = new StopsAPI({\n * url: 'https://api.geops.io/stops/v1/',\n * apiKey: [yourApiKey]\n * });\n *\n */\nclass StopsAPI extends API {\n /**\n * Constructor\n *\n * @param {Object} options Options.\n * @param {string} [options.url='https://api.geops.io/stops/v1/'] Service url.\n * @param {string} options.apiKey Access key for [geOps services](https://developer.geops.io/).\n */\n constructor(options = {}) {\n super({ url: 'https://api.geops.io/stops/v1/', ...options });\n }\n\n /**\n * Search.\n *\n * @param {StopsSearchParams} params Request parameters. See [Stops service documentation](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).\n * @param {AbortController} abortController Abort controller used to cancel the request.\n * @return {Promise<Array<GeoJSONFeature>>} An array of GeoJSON features with coordinates in [EPSG:4326](http://epsg.io/4326).\n */\n search(params, abortController = {}) {\n return this.fetch('', params, {\n signal: abortController.signal,\n }).then((featureCollection) => featureCollection.features);\n }\n}\n\nexport default StopsAPI;\n","/**\n * Class used to facilitate connection to a WebSocket and\n * also to manage properly messages send to the WebSocket.\n * This class must not contain any specific implementation.\n *\n * @private\n */\nclass WebSocketConnector {\n constructor() {\n this.defineProperties();\n }\n\n defineProperties() {\n Object.defineProperties(this, {\n closed: {\n get: () =>\n !!(\n this.websocket &&\n this.websocket.readyState === this.websocket.CLOSED\n ),\n },\n closing: {\n get: () =>\n !!(\n this.websocket &&\n this.websocket.readyState === this.websocket.CLOSING\n ),\n },\n connecting: {\n get: () =>\n !!(\n this.websocket &&\n this.websocket.readyState === this.websocket.CONNECTING\n ),\n },\n open: {\n get: () =>\n !!(\n this.websocket && this.websocket.readyState === this.websocket.OPEN\n ),\n },\n /**\n * Array of message to send on open.\n * @type {Array<string>}\n * @private\n */\n messagesOnOpen: {\n value: [],\n writable: true,\n },\n /**\n * Array of subscriptions.\n * @type {Array<subscription>}\n * @private\n */\n subscriptions: {\n value: [],\n writable: true,\n },\n\n /**\n * List of channels subscribed.\n * @type {Array<subscription>}\n * @private\n */\n subscribed: {\n value: {},\n writable: true,\n },\n });\n }\n\n /**\n * Get the websocket request string.\n *\n * @param {string} method Request mehtod {GET, SUB}.\n * @param {Object} params Request parameters.\n * @param {string} params.channel Channel name\n * @param {string} [params.args] Request arguments\n * @param {Number} [params.id] Request identifier\n * @return {string} request string\n * @private\n */\n static getRequestString(method, params) {\n let reqStr = `${method} ${params.channel}`;\n reqStr += params.args ? ` ${params.args}` : '';\n reqStr += params.id ? ` ${params.id}` : '';\n return reqStr.trim();\n }\n\n /**\n * (Re)connect the websocket.\n *\n * @param {strin} url Websocket url.\n * @param {function} onOpen Callback called when the websocket connection is opened and before subscriptions of previous subscriptions.\n * @private\n */\n connect(url, onOpen = () => {}) {\n if (this.websocket && !this.closed) {\n this.websocket.close();\n }\n\n /** @ignore */\n this.websocket = new WebSocket(url);\n\n if (!this.open) {\n this.websocket.addEventListener('open', () => {\n onOpen();\n this.subscribePreviousSubscriptions();\n });\n } else {\n onOpen();\n this.subscribePreviousSubscriptions();\n }\n }\n\n /**\n * Close the websocket definitively.\n *\n * @private\n */\n close() {\n if (this.websocket) {\n this.websocket.onclose = null;\n this.websocket.close();\n this.websocket = null;\n this.messagesOnOpen = [];\n }\n }\n\n /**\n * Sends a message to the websocket.\n *\n * @param {message} message Message to send.\n * @private\n */\n send(message) {\n if (!this.websocket) {\n return;\n }\n const send = () => {\n this.websocket.send(message);\n };\n if (!this.open) {\n // This 'if' avoid sending 2 identical BBOX message on open,\n if (!this.messagesOnOpen.includes(message)) {\n this.messagesOnOpen.push(message);\n this.websocket.addEventListener('open', () => {\n this.messagesOnOpen = [];\n send();\n });\n this.websocket.addEventListener('close', () => {\n this.messagesOnOpen = [];\n });\n }\n } else if (!this.messagesOnOpen.includes(message)) {\n send();\n }\n }\n\n /**\n * Listen to websocket messages.\n *\n * @param {Object} params Parameters for the websocket get request\n * @param {function} cb callback on listen\n * @param {function} errorCb Callback on error\n * @return {{onMessage: function, errorCb: function}} Object with onMessage and error callbacks\n * @private\n */\n listen(params, cb, errorCb) {\n // Remove the previous identical callback\n this.unlisten(params, cb);\n\n const onMessage = (evt) => {\n let data = {};\n try {\n data = JSON.parse(evt.data);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('WebSocket: unable to parse JSON data', err, evt.data);\n }\n let source = params.channel;\n source += params.args ? ` ${params.args}` : '';\n\n // Buffer channel message return a list of other channels to propagate to proper callbacks.\n const contents = data.source === 'buffer' ? data.content : [data];\n contents.forEach((content) => {\n // Because of backend optimization, the last content is null.\n if (\n content?.source === source &&\n (!params.id || params.id === data.client_reference)\n ) {\n cb(content);\n }\n });\n };\n\n if (this.websocket) {\n this.websocket.addEventListener('message', onMessage);\n\n if (errorCb) {\n this.websocket.addEventListener('error', errorCb);\n this.websocket.addEventListener('close', errorCb);\n }\n }\n\n return { onMessageCb: onMessage, onErrorCb: errorCb };\n }\n\n /**\n * Unlisten websocket messages.\n *\n * @param {Object} params Parameters for the websocket get request.\n * @param {function} cb Callback used when listen.\n * @private\n */\n unlisten(params, cb) {\n if (!this.websocket) {\n return;\n }\n this.subscriptions\n .filter(\n (s) => s.params.channel === params.channel && (!cb || s.cb === cb),\n )\n .forEach(({ onMessageCb, onErrorCb }) => {\n if (this.websocket) {\n this.websocket.removeEventListener('message', onMessageCb);\n if (onErrorCb) {\n this.websocket.removeEventListener('error', onErrorCb);\n this.websocket.removeEventListener('close', onErrorCb);\n }\n }\n });\n }\n\n /**\n * Sends a get request to the websocket.\n *\n * @param {Object} params Parameters for the websocket get request\n * @param {function} cb callback on listen\n * @param {function} errorCb Callback on error\n * @private\n */\n get(params, cb, errorCb) {\n const reqStr = WebSocketConnector.getRequestString('GET', params);\n this.send(reqStr);\n this.listen(params, cb, errorCb);\n }\n\n /**\n * Subscribe to a given channel.\n *\n * @param {Object} params Parameters for the websocket get request\n * @param {function} cb callback on listen\n * @param {function} errorCb Callback on error\n * @param {boolean} quiet if false, no GET or SUB requests are send, only the callback is registered.\n * @private\n */\n subscribe(params, cb, errorCb, quiet = false) {\n const { onMessageCb, onErrorCb } = this.listen(params, cb, errorCb);\n const reqStr = WebSocketConnector.getRequestString('', params);\n\n const index = this.subscriptions.findIndex(\n (subcr) => params.channel === subcr.params.channel && cb === subcr.cb,\n );\n const newSubscr = { params, cb, errorCb, onMessageCb, onErrorCb, quiet };\n if (index > -1) {\n this.subscriptions[index] = newSubscr;\n } else {\n this.subscriptions.push(newSubscr);\n }\n\n if (!this.subscribed[reqStr]) {\n if (!newSubscr.quiet) {\n this.send(`GET ${reqStr}`);\n this.send(`SUB ${reqStr}`);\n }\n this.subscribed[reqStr] = true;\n }\n }\n\n /**\n * Unsubscribe from a channel.\n * @param {string} source source to unsubscribe from\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n * @private\n */\n unsubscribe(source, cb) {\n const toRemove = this.subscriptions.filter(\n (s) => s.params.channel === source && (!cb || s.cb === cb),\n );\n\n toRemove.forEach(({ onMessageCb, onErrorCb }) => {\n if (this.websocket) {\n this.websocket.removeEventListener('message', onMessageCb);\n if (onErrorCb) {\n this.websocket.removeEventListener('error', onErrorCb);\n this.websocket.removeEventListener('close', onErrorCb);\n }\n }\n });\n\n this.subscriptions = this.subscriptions.filter(\n (s) => s.params.channel !== source || (cb && s.cb !== cb),\n );\n\n // If there is no more subscriptions to this channel, and the removed subscriptions didn't register quietly,\n // we DEL it.\n if (\n source &&\n this.subscribed[source] &&\n !this.subscriptions.find((s) => s.params.channel === source) &&\n toRemove.find((subscr) => !subscr.quiet)\n ) {\n this.send(`DEL ${source}`);\n this.subscribed[source] = false;\n }\n }\n\n /**\n * After an auto reconnection we need to re-subscribe to the channels.\n */\n subscribePreviousSubscriptions() {\n // Before to subscribe previous subscriptions we make sure they\n // are all defined as unsubscribed, because this code is asynchrone\n // and a subscription could have been added in between.\n Object.keys(this.subscribed).forEach((key) => {\n this.subscribed[key] = false;\n });\n\n // Subscribe all previous subscriptions.\n [...this.subscriptions].forEach((s) => {\n this.subscribe(s.params, s.cb, s.errorCb, s.quiet);\n });\n }\n}\n\nexport default WebSocketConnector;\n","/**\n * Get the websocket channel suffix, depending on the current mode.\n * @param {String} mode Mode 'topographic' ou 'schematic'.\n * @private\n */\nexport const getModeSuffix = (mode, modes) =>\n mode === modes.SCHEMATIC ? '_schematic' : '';\n\n/**\n * Compare two given departures for sort alogithm,\n * @param {Object} a First departure.\n * @param {Object} b Second departure.\n * @private\n */\nexport const compareDepartures = (a, b, sortByMinArrivalTime = false) => {\n // First LEAVING and HIDDEN, then BOARDING and then sorted by time.\n const topStates = ['HIDDEN', 'LEAVING', 'BOARDING'];\n const aTop = a.has_fzo && topStates.indexOf(a.state) > -1;\n const bTop = b.has_fzo && topStates.indexOf(b.state) > -1;\n\n if (aTop || bTop) {\n if (aTop !== bTop) {\n return aTop ? -1 : 1;\n }\n\n if (a.state !== b.state) {\n // one is leaving\n return topStates.indexOf(a.state) - topStates.indexOf(b.state);\n }\n }\n\n let aDuration = null;\n let bDuration = null;\n const now = Date.now();\n\n if (sortByMinArrivalTime) {\n aDuration = new Date(a.min_arrival_time || a.time).getTime() - now;\n bDuration = new Date(b.min_arrival_time || b.time).getTime() - now;\n } else {\n aDuration = new Date(a.time).getTime() - now;\n bDuration = new Date(b.time).getTime() - now;\n }\n\n return aDuration - bDuration;\n};\n\n/**\n * Remove the delay from arrivalTime and departureTime\n * @private\n */\nexport const cleanStopTime = (content) => {\n if (!content) {\n return;\n }\n content.stations.forEach((station) => {\n // eslint-disable-next-line no-param-reassign\n station.arrivalTimeWithDelay = station.arrivalTime;\n if (station.departureTime) {\n // eslint-disable-next-line no-param-reassign\n station.departureTimeWithDelay = station.departureTime;\n }\n if (station.arrivalDelay) {\n // eslint-disable-next-line no-param-reassign\n station.arrivalTime -= station.arrivalDelay;\n if (station.departureTime) {\n // eslint-disable-next-line no-param-reassign\n station.departureTime -= station.arrivalDelay;\n }\n }\n });\n // eslint-disable-next-line consistent-return\n return content;\n};\n","import WebSocketConnector from './WebSocketConnector';\nimport {\n getModeSuffix,\n cleanStopTime,\n compareDepartures,\n} from './TralisAPIUtils';\n\n/**\n * Enum for Tralis modes.\n * @readonly\n * @typedef {string} TralisMode\n * @property {string} RAW \"raw\"\n * @property {string} SCHEMATIC \"schematic\"\n * @property {string} TOPOGRAPHIC \"topographic\"\n * @enum {TralisMode}\n */\nexport const TralisModes = {\n RAW: 'raw',\n TOPOGRAPHIC: 'topographic',\n SCHEMATIC: 'schematic',\n};\n\n/**\n * This class provides convenience methods to access to the [geOps realtime api](https://developer.geops.io/apis/realtime/).\n *\n * @example\n * import { TralisAPI } from 'mobility-toolbox-js/api';\n *\n * const api = new TralisAPI({\n * url: \"yourUrl\",\n * apiKey: \"yourApiKey\"\n * });\n *\n * @example\n * import { TralisAPI } from 'mobility-toolbox-js/api';\n *\n * const api = new TralisAPI(\"yourUrl\");\n */\nclass TralisAPI {\n /**\n * Constructor\n *\n * @param {Object|string} options A string representing the url of the service or an object containing the url and the apiKey.\n * @param {string} options.url Url to the [geOps realtime api](https://developer.geops.io/apis/realtime/).\n * @param {string} options.apiKey Access key for [geOps apis](https://developer.geops.io/).\n * @param {string} [options.prefix=''] Service prefix to specify tenant.\n * @param {string} [options.projection] The epsg code of the projection for features. Default to EPSG:3857.\n * @param {number[4]} [options.bbox=[minX, minY, maxX, maxY, zoom, tenant] The bounding box to receive data from.\n */\n constructor(options = {}) {\n this.defineProperties(options);\n\n /** @ignore */\n this.subscribedStationUic = null;\n\n /** @ignore */\n this.departureUpdateTimeout = null;\n\n /** @ignore */\n this.maxDepartureAge = 30;\n\n /** @ignore */\n this.extraGeoms = {};\n\n /** @ignore */\n this.prefix = options.prefix || '';\n\n /** @ignore */\n this.onOpen = this.onOpen.bind(this);\n }\n\n defineProperties(options) {\n let opt = options;\n\n if (typeof options === 'string') {\n opt = { url: options };\n }\n\n const { apiKey } = opt;\n let { url, projection, bbox, buffer = [100, 100] } = opt;\n const conn = new WebSocketConnector();\n\n if (apiKey) {\n url = `${url || 'wss://api.geops.io/tracker-ws/v1/'}?key=${apiKey}`;\n }\n\n Object.defineProperties(this, {\n url: {\n get: () => url,\n set: (newUrl) => {\n url = newUrl;\n this.open();\n },\n },\n projection: {\n get: () => projection,\n set: (newProjection) => {\n if (newProjection !== projection) {\n projection = newProjection;\n if (this.conn) {\n this.conn.send(`PROJECTION ${projection}`);\n }\n }\n },\n },\n bbox: {\n get: () => bbox,\n set: (newBbox) => {\n if (JSON.stringify(newBbox) !== JSON.stringify(bbox)) {\n bbox = newBbox;\n if (this.conn) {\n this.conn.send(`BBOX ${bbox.join(' ')}`);\n }\n }\n },\n },\n buffer: {\n get: () => buffer,\n set: (newBuffer) => {\n if (JSON.stringify(newBuffer) !== JSON.stringify(buffer)) {\n buffer = newBuffer;\n if (this.conn) {\n this.conn.send(`BUFFER ${buffer.join(' ')}`);\n }\n }\n },\n },\n /**\n * The websocket helper class to connect the websocket.\n *\n * @private\n */\n conn: {\n value: conn,\n writable: true,\n },\n /**\n * Interval between PING request in ms.\n * If equal to 0, no PING request are sent.\n * @type {number}\n * @private\n */\n pingIntervalMs: {\n value: options.pingIntervalMs || 10000,\n writable: true,\n },\n /**\n * Timeout in ms after an automatic reconnection when the websoscket has been closed by the server.\n * @type {number}\n */\n reconnectTimeoutMs: {\n value: options.pingIntervalMs || 100,\n writable: true,\n },\n });\n }\n\n open() {\n this.close();\n // Register BBOX and PROJECTION messages must be send before previous subscriptions.\n this.conn.connect(this.url, this.onOpen);\n\n // Register reconnection on close.\n this.conn.websocket.onclose = () => {\n this.onClose();\n };\n }\n\n /**\n * Close the websocket connection without reconnection.\n */\n close() {\n this.conn.close();\n }\n\n /**\n * Unsubscribe trajectory and deleted_vehicles channels. To resubscribe you have to set a new BBOX.\n */\n // eslint-disable-next-line class-methods-use-this\n reset() {\n this.conn.send('RESET');\n }\n\n /**\n * Callback when the websocket is opened and ready.\n * It applies the bbox and the projection.\n */\n onOpen() {\n if (this.projection) {\n this.conn.send(`PROJECTION ${this.projection}`);\n }\n\n if (this.bbox) {\n this.conn.send(`BBOX ${this.bbox.join(' ')}`);\n }\n\n if (this.buffer) {\n this.conn.send(`BUFFER ${this.buffer.join(' ')}`);\n }\n\n /**\n * Keep websocket alive\n */\n if (this.pingIntervalMs) {\n window.clearInterval(this.pingInterval);\n /** @ignore */\n this.pingInterval = setInterval(() => {\n this.conn.send('PING');\n }, this.pingIntervalMs);\n }\n }\n\n /**\n * Callback when the websocket is closed by the server.\n * It auto reconnects after a timeout.\n */\n onClose() {\n window.clearTimeout(this.pingInterval);\n window.clearTimeout(this.reconnectTimeout);\n\n if (this.reconnectTimeoutMs) {\n /** @ignore */\n this.reconnectTimeout = window.setTimeout(\n () => this.open(),\n this.reconnectTimeoutMs,\n );\n }\n }\n\n /**\n * Subscribe to a channel.\n *\n * @param {string} channel Name of the websocket channel to subscribe.\n * @param {function} onSuccess Callback when the subscription succeeds.\n * @param {function} onError Callback when the subscription fails.\n * @param {boolean} [quiet=false] If true avoid to store the subscription in the subscriptions list.\n * @private\n */\n subscribe(channel, onSuccess, onError, quiet = false) {\n this.conn.subscribe({ channel }, onSuccess, onError, quiet);\n }\n\n /**\n * Unsubscribe both modes of a channel.\n *\n * @param {string} channel Name of the websocket channel to unsubscribe.\n * @param {string} suffix Suffix to add to the channel name.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n * @private\n */\n unsubscribe(channel, suffix, cb) {\n this.conn.unsubscribe(\n `${channel}${getModeSuffix(TralisModes.SCHEMATIC, TralisModes)}${suffix}`,\n cb,\n );\n this.conn.unsubscribe(\n `${channel}${getModeSuffix(TralisModes.TOPOGRAPHIC, TralisModes)}${\n suffix || ''\n }`,\n cb,\n );\n }\n\n /**\n * Filter departures and return an array.\n *\n * @param {Object} depObject The object containing departures by id.\n * @param {boolean} [sortByMinArrivalTime=false] If true sort departures by arrival time.\n * @return {Array<departure>} Return departures array.\n * @private\n */\n filterDepartures(depObject, sortByMinArrivalTime = false) {\n const departures = Object.keys(depObject).map((k) => depObject[k]);\n departures.sort((a, b) => compareDepartures(a, b, sortByMinArrivalTime));\n\n let future = new Date();\n future.setMinutes(future.getMinutes() + this.maxDepartureAge);\n future = future.getTime();\n\n let past = new Date();\n past.setMinutes(past.getMinutes() - this.maxDepartureAge);\n past = past.getTime();\n\n const departureArray = [];\n const platformsBoarding = [];\n let previousDeparture = null;\n\n for (let i = departures.length - 1; i >= 0; i -= 1) {\n const d = departures[i];\n const t = new Date(d.time).getTime();\n\n // Only show departures within the next 30 minutes\n if (t > past && t < future) {\n // If 2 trains are boarding at the same platform,\n // remove the older one.\n if (d.state === 'BOARDING') {\n if (platformsBoarding.indexOf(d.platform) === -1) {\n platformsBoarding.push(d.platform);\n } else {\n d.state = 'HIDDEN';\n }\n }\n\n // If two trains with the same line number and destinatin\n // and a departure difference < 1 minute, hide the second one.\n if (\n previousDeparture &&\n d.to[0] === previousDeparture.to[0] &&\n Math.abs(t - previousDeparture.time) < 1000 &&\n d.line.name === previousDeparture.line.name\n ) {\n d.state = 'HIDDEN';\n }\n\n if (/(STOP_CANCELLED|JOURNEY_CANCELLED)/.test(d.state)) {\n d.cancelled = true;\n }\n\n previousDeparture = d;\n previousDeparture.time = t;\n departureArray.unshift(d);\n }\n }\n\n return departureArray;\n }\n\n /**\n * Subscribe to departures channel of a given station.\n *\n * @param {number} stationId UIC of the station.\n * @param {Boolean} sortByMinArrivalTime Sort by minimum arrival time\n * @param {function(departures:Departure[])} onMessage Function called on each message of the channel.\n */\n subscribeDepartures(stationId, sortByMinArrivalTime, onMessage) {\n window.clearTimeout(this.departureUpdateTimeout);\n this.unsubscribeDepartures();\n this.subscribedStationUic = stationId;\n const channel = stationId ? `timetable_${stationId}` : null;\n const departureObject = {};\n this.subscribe(\n channel,\n (data) => {\n if (data.source === channel) {\n const content = data.content || {};\n const tDiff = new Date(content.timestamp).getTime() - Date.now();\n content.timediff = tDiff;\n departureObject[content.call_id] = content;\n\n window.clearTimeout(this.departureUpdateTimeout);\n this.departureUpdateTimeout = window.setTimeout(() => {\n const departures = this.filterDepartures(\n departureObject,\n sortByMinArrivalTime || false,\n );\n onMessage(departures);\n }, 100);\n }\n },\n () => {\n onMessage([]);\n },\n );\n }\n\n /**\n * Unsubscribe from current departures channel.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeDepartures(cb) {\n if (this.subscribedStationUic) {\n this.unsubscribe(`timetable_${this.subscribedStationUic}`, '', cb);\n this.subscribedStationUic = null;\n }\n }\n\n /**\n * Subscribe to the disruptions channel for tenant.\n *\n * @param {function} onMessage Function called on each message of the channel.\n */\n subscribeDisruptions(onMessage) {\n this.subscribe(`${this.prefix}newsticker`, (data) => {\n onMessage(data.content);\n });\n }\n\n /**\n * Unsubscribe disruptions.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeDisruptions(cb) {\n this.unsubscribe(`${this.prefix}newsticker`, '', cb);\n }\n\n /**\n * Return a station with a given uic number and a mode.\n *\n * @param {number} uic UIC of the station.\n * @param {TralisMode} mode Tralis mode.\n * @return {Promise<Station>} A station.\n */\n getStation(uic, mode) {\n const params = {\n channel: `station${getModeSuffix(mode, TralisModes)}`,\n args: uic,\n };\n\n return new Promise((resolve, reject) => {\n this.conn.get(params, (data) => {\n if (data.content) {\n resolve(data.content);\n } else {\n reject();\n }\n });\n });\n }\n\n /**\n * Update the model's station list for a given mode and a bbox.\n *\n * @param {TralisMode} mode Tralis mode.\n * @return {Promise<Array<Station>>} An array of stations.\n */\n getStations(mode) {\n const stations = [];\n const params = {\n channel: `station${getModeSuffix(mode, TralisModes)}`,\n };\n window.clearTimeout(this.stationUpdateTimeout);\n return new Promise((resolve, reject) => {\n this.conn.get(params, (data) => {\n if (data.content) {\n stations.push(data.content);\n window.clearTimeout(this.stationUpdateTimeout);\n /** @ignore */\n this.stationUpdateTimeout = window.setTimeout(() => {\n resolve(stations);\n }, 50);\n } else {\n reject(data.content);\n }\n });\n });\n }\n\n /**\n * Subscribe to stations channel.\n * One message pro station.\n *\n * @param {TralisMode} mode Tralis mode.\n * @param {function(station: Station)} onMessage Function called on each message of the channel.\n */\n subscribeStations(mode, onMessage) {\n this.unsubscribeStations();\n this.subscribe(`station${getModeSuffix(mode, TralisModes)}`, (data) => {\n if (data.content) {\n onMessage(data.content);\n }\n });\n }\n\n /**\n * Unsubscribe to stations channel.\n * @param {function} cb The listener callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribe.\n */\n unsubscribeStations(cb) {\n window.clearTimeout(this.stationUpdateTimeout);\n this.unsubscribe('station', '', cb);\n }\n\n /**\n * Subscribe to extra_geoms channel.\n *\n * @param {function(extraGeoms: GeosJSONFeature[])} onMessage Function called on each message of the channel.\n */\n subscribeExtraGeoms(onMessage) {\n this.subscribe('extra_geoms', (data) => {\n const extraGeom = data.content;\n\n if (extraGeom) {\n const { ref } = extraGeom.properties;\n\n if (extraGeom.type === 'Feature') {\n this.extraGeoms[ref] = extraGeom;\n } else {\n delete this.extraGeoms[ref];\n }\n\n onMessage(\n Object.keys(this.extraGeoms).map((key) => this.extraGeoms[key]),\n );\n }\n });\n }\n\n /**\n * Unsubscribe to extra_geoms channel.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeExtraGeoms(cb) {\n this.unsubscribe('extra_geoms', '', cb);\n }\n\n /**\n * Subscribe to trajectory channel.\n *\n * @param {TralisMode} mode Tralis mode.\n * @param {function(trajectory: TralisTrajectory)} onMessage Function called on each message of the channel.\n * @param {boolean} quiet If true, the subscription will not send GET and SUB requests to the websocket.\n */\n subscribeTrajectory(mode, onMessage, quiet = false) {\n this.unsubscribeTrajectory(onMessage);\n this.subscribe(\n `trajectory${getModeSuffix(mode, TralisModes)}`,\n onMessage,\n null,\n quiet,\n );\n }\n\n /**\n * Unsubscribe to trajectory channels.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeTrajectory(cb) {\n this.unsubscribe(`trajectory`, '', cb);\n }\n\n /**\n * Subscribe to deleted_vhicles channel.\n *\n * @param {TralisMode} mode Tralis mode.\n * @param {function(response: { content: Vehicle })} onMessage Function called on each message of the channel.\n * @param {boolean} quiet If true, the subscription will not send GET and SUB requests to the websocket.\n */\n subscribeDeletedVehicles(mode, onMessage, quiet = false) {\n this.unsubscribeDeletedVehicles(onMessage);\n this.subscribe(\n `deleted_vehicles${getModeSuffix(mode, TralisModes)}`,\n onMessage,\n null,\n quiet,\n );\n }\n\n /**\n * Unsubscribe to deleted_vhicles channels.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeDeletedVehicles(cb) {\n this.unsubscribe('deleted_vehicles', '', cb);\n }\n\n /**\n * Get a full trajectory of a vehicule .\n *\n * @param {string} id A vehicle id.\n * @param {TralisMode} mode Tralis mode.\n * @param {string} generalizationLevel The generalization level to request. Can be one of 5 (more generalized), 10, 30, 100, undefined (less generalized).\n * @return {Promise<FullTrajectory>} Return a full trajectory.\n */\n getFullTrajectory(id, mode, generalizationLevel) {\n const channel = [`full_trajectory${getModeSuffix(mode, TralisModes)}`];\n if (id) {\n channel.push(id);\n }\n\n if ((!mode || mode === TralisModes.TOPOGRAPHIC) && generalizationLevel) {\n channel.push(`gen${generalizationLevel}`);\n }\n\n const params = {\n channel: channel.join('_'),\n };\n\n return new Promise((resolve) => {\n this.conn.get(params, (data) => {\n if (data.content) {\n resolve(data.content);\n }\n });\n });\n }\n\n /**\n * Get full trajectories of a vehicules .\n *\n * @param {string[]} ids List of vehicles ids.\n * @param {TralisMode} mode Tralis mode.\n * @param {string} generalizationLevel The generalization level to request. Can be one of '', 'gen5', 'gen10', 'gen30', 'gen100'.\n * @return {Promise<Array<FullTrajectory>>} Return an array of full trajectories.\n */\n getFullTrajectories(ids, mode, generalizationLevel) {\n const promises = ids.map((id) =>\n this.getFullTrajectory(id, mode, generalizationLevel),\n );\n return Promise.all(promises);\n }\n\n /**\n * Subscribe to full_trajectory channel of a given vehicle.\n *\n * @param {string} id A vehicle id.\n * @param {TralisMode} mode Tralis mode.\n */\n subscribeFullTrajectory(id, mode) {\n // window.clearTimeout(this.fullTrajectoryUpdateTimeout);\n this.unsubscribeFullTrajectory(id);\n this.subscribe(\n `full_trajectory${getModeSuffix(mode, TralisModes)}_${id}`,\n (data) => {\n // eslint-disable-next-line no-console\n console.log('subscribe full_trajectory', data);\n },\n (err) => {\n // eslint-disable-next-line no-console\n console.log('subscribe full_trajectory error', err);\n },\n );\n }\n\n /**\n * Unsubscribe from full_trajectory channel\n *\n * @param {string} id A vehicle id.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeFullTrajectory(id, cb) {\n this.unsubscribe('full_trajectory', `_${id}`, cb);\n }\n\n /**\n * Get the list of stops for this vehicle.\n *\n * @param {string} id A vehicle id.\n * @return {Promise<StopSequence>} Returns a stop sequence object.\n */\n getStopSequence(id) {\n const params = {\n channel: `stopsequence_${id}`,\n };\n return new Promise((resolve, reject) => {\n this.conn.get(\n params,\n (data) => {\n if (data.content && data.content.length) {\n const content = data.content.map((stopSequence) =>\n cleanStopTime(stopSequence),\n );\n\n // Remove the delay from arrivalTime and departureTime\n resolve(content);\n }\n resolve([]);\n },\n (err) => {\n reject(err);\n },\n );\n });\n }\n\n /**\n * Get a list of stops for a list of vehicles.\n *\n * @param {string[]} ids List of vehicles ids.\n * @return {Promise<Array<StopSequence>>} Return an array of stop sequences.\n */\n getStopSequences(ids) {\n const promises = ids.map((id) => this.getStopSequence(id));\n return Promise.all(promises);\n }\n\n /**\n * Subscribe to stopsequence channel of a given vehicle.\n *\n * @param {string} id A vehicle id.\n * @param {function(stopSequence: StopSequence)} onMessage Function called on each message of the channel.\n */\n subscribeStopSequence(id, onMessage) {\n window.clearTimeout(this.fullTrajectoryUpdateTimeout);\n this.unsubscribeStopSequence(id);\n\n this.subscribe(\n `stopsequence_${id}`,\n (data) => {\n if (data.content && data.content.length) {\n const content = data.content.map((stopSequence) =>\n cleanStopTime(stopSequence),\n );\n\n // Remove the delay from arrivalTime and departureTime\n onMessage(content);\n }\n },\n (err) => {\n // eslint-disable-next-line no-console\n console.log('subscribe stopsequence error', err);\n },\n );\n }\n\n /**\n * Unsubscribe from stopsequence channel\n *\n * @param {string} id A vehicle id.\n * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.\n */\n unsubscribeStopSequence(id, cb) {\n this.unsubscribe(`stopsequence`, `_${id}`, cb);\n }\n\n /**\n * Subscribe to healthcheck channel.\n * @param {function} onMessage Callback when the subscribe to healthcheck channel succeeds.\n */\n subscribeHealthCheck(onMessage) {\n this.unsubscribeHealthCheck();\n this.subscribe('healthcheck', onMessage);\n }\n\n /**\n * Unsubscribe to healthcheck channel.\n */\n unsubscribeHealthCheck() {\n this.unsubscribe('healthcheck');\n }\n}\nexport default TralisAPI;\n","/* eslint-disable no-empty-function */\n/* eslint-disable no-useless-constructor */\n/* eslint-disable no-unused-vars */\n/* eslint-disable class-methods-use-this */\n/* eslint-disable max-classes-per-file */\nimport qs from 'query-string';\nimport { buffer, containsCoordinate, intersects } from 'ol/extent';\nimport { unByKey } from 'ol/Observable';\nimport GeoJSON from 'ol/format/GeoJSON';\nimport Point from 'ol/geom/Point';\nimport debounce from 'lodash.debounce';\nimport throttle from 'lodash.throttle';\nimport { fromLonLat } from 'ol/proj';\nimport Tracker from '../Tracker';\nimport { timeSteps } from '../trackerConfig';\nimport createFilters from '../utils/createTrackerFilters';\nimport trackerDefaultStyle from '../styles/trackerDefaultStyle';\nimport { TralisAPI, TralisModes } from '../../api';\n\n/* Permalink parameter used to filters vehicles */\nconst LINE_FILTER = 'publishedlinename';\nconst ROUTE_FILTER = 'tripnumber';\nconst OPERATOR_FILTER = 'operator';\n\n/**\n * TralisLayerInterface.\n */\nexport class TralisLayerInterface {\n /*\n * Constructor\n\n * @param {Object} options Layer options.\n * @param {string} options.url Tralis service url.\n * @param {string} options.apiKey Access key for [geOps services](https://developer.geops.io/).\n * @param {boolean} [options.debug=false] Display additional debug informations.\n * @param {TralisMode} [options.mode=TralisMode.TOPOGRAPHIC] Tralis's Mode.\n * @param {number} [options.minZoomInterpolation=8] Minimal zoom when trains positions start to be interpolated.\n * @param {number} [options.minZoomNonTrain=9] Minimal zoom when non trains vehicles are allowed to be displayed.\n */\n constructor(options = {}) {}\n\n /**\n * Initialize the layer subscribing to the Tralis api.\n *\n * @param {ol/Map~Map} map\n */\n init(map) {}\n\n /**\n * Terminate the layer unsubscribing to the Tralis api.\n */\n terminate() {}\n\n /**\n * Start the clock.\n */\n start() {}\n\n /**\n * Stop the clock.\n */\n stop() {}\n\n /**\n * Set the Tralis api's bbox.\n *\n * @param {Array<number>} extent Extent to request, [minX, minY, maxX, maxY, zoom].\n * @param {number} zoom Zoom level to request. Must be an integer.\n */\n setBbox(extent, zoom) {}\n\n /**\n * Set the Tralis api's mode.\n *\n * @param {TralisMode} mode Tralis mode\n */\n setMode(mode) {}\n\n /**\n * Request the stopSequence and the fullTrajectory informations for a vehicle.\n *\n * @param {string} id The vehicle identifier (the train_id property).\n * @param {TralisMode} mode The mode to request. If not defined, the layer´s mode propetrty will be used.\n * @return {Promise<{stopSequence: StopSequence, fullTrajectory: FullTrajectory>} A promise that will be resolved with the trajectory informations.\n */\n getTrajectoryInfos(id, mode) {}\n}\n\n/**\n * Mixin for TralisLayerInterface.\n *\n * @param {Class} Base A class to extend with {TralisLayerInterface} functionnalities.\n * @return {Class} A class that implements {TralisLayerInterface} class and extends Base;\n * @private\n */\nconst TralisLayerMixin = (Base) =>\n class extends Base {\n constructor(options = {}) {\n super({ hitTolerance: 10, ...options });\n\n this.debug = options.debug;\n this.mode = options.mode || TralisModes.TOPOGRAPHIC;\n this.api = options.api || new TralisAPI(options);\n this.tenant = options.tenant || ''; // sbb,sbh or sbm\n this.minZoomNonTrain = options.minZoomNonTrain || 9; // Min zoom level from which non trains are allowed to be displayed. Min value is 9 (as configured by the server\n this.minZoomInterpolation = options.minZoomInterpolation || 8; // Min zoom level from which trains positions are not interpolated.\n this.format = new GeoJSON();\n this.generalizationLevelByZoom = options.generalizationLevelByZoom || {\n 0: 5,\n 1: 5,\n 2: 5,\n 3: 5,\n 4: 5,\n 5: 5,\n 6: 5,\n 7: 5,\n 8: 10,\n 9: 30,\n 10: 30,\n 11: 100,\n 12: 100,\n 13: 100,\n };\n\n // This property will call api.setBbox on each movend event\n this.isUpdateBboxOnMoveEnd = options.isUpdateBboxOnMoveEnd !== false;\n\n // Define throttling nad debounce render function\n this.throttleRenderTrajectories = throttle(\n this.renderTrajectoriesInternal,\n 50,\n { leading: false, trailing: true },\n );\n\n this.debounceRenderTrajectories = debounce(\n this.renderTrajectoriesInternal,\n 50,\n { leading: true, trailing: true, maxWait: 5000 },\n );\n\n // Bind callbacks\n this.onFeatureHover = this.onFeatureHover.bind(this);\n this.onFeatureClick = this.onFeatureClick.bind(this);\n this.renderTrajectoriesInternal =\n this.renderTrajectoriesInternal.bind(this);\n this.onTrajectoryMessage = this.onTrajectoryMessage.bind(this);\n this.onDeleteTrajectoryMessage =\n this.onDeleteTrajectoryMessage.bind(this);\n this.onDocumentVisibilityChange =\n this.onDocumentVisibilityChange.bind(this);\n }\n\n /**\n * Define layer's properties.\n *\n * @ignore\n */\n defineProperties(options) {\n // Tracker options use to build the tracker.\n let { regexPublishedLineName, publishedLineName, tripNumber, operator } =\n options;\n const {\n style,\n speed,\n pixelRatio,\n hoverVehicleId,\n selectedVehicleId,\n filter,\n sort,\n time,\n live,\n } = options;\n\n const initTrackerOptions = {\n style,\n };\n\n Object.keys(initTrackerOptions).forEach(\n (key) =>\n initTrackerOptions[key] === undefined &&\n delete initTrackerOptions[key],\n );\n\n let currSpeed = speed || 1;\n let currTime = time || new Date();\n\n super.defineProperties(options);\n\n Object.defineProperties(this, {\n isTrackerLayer: { value: true },\n\n /**\n * Style function used to render a vehicle.\n */\n style: {\n value: (trajectory, viewState) =>\n (style || trackerDefaultStyle)(trajectory, viewState, this),\n },\n\n /**\n * Speed of the wheel of time.\n * If live property is true. The speed is ignored.\n */\n speed: {\n get: () => currSpeed,\n set: (newSpeed) => {\n currSpeed = newSpeed;\n this.start();\n },\n },\n\n /**\n * Function to filter which vehicles to display.\n */\n filter: {\n value: filter,\n writable: true,\n },\n\n /**\n * Function to sort the vehicles to display.\n */\n sort: {\n value: sort,\n writable: true,\n },\n\n /**\n * The tracker that renders the trajectories.\n */\n tracker: { value: null, writable: true },\n\n /**\n * Canvas cache object for trajectories drawn.\n */\n styleCache: { value: {} },\n\n /**\n * If true. The layer will always use Date.now() on the next tick to render the trajectories.\n * When true, setting the time property has no effect.\n */\n live: {\n value: live === false ? live : true,\n writable: true,\n },\n\n /**\n * Time used to display the trajectories. Can be a Date or a number in ms representing a Date.\n * If live property is true. The setter does nothing.\n */\n time: {\n get: () => currTime,\n set: (newTime) => {\n currTime = newTime && newTime.getTime ? newTime : new Date(newTime);\n this.renderTrajectories();\n },\n },\n\n /**\n * Keep track of which trajectories are stored.\n */\n trajectories: {\n value: {},\n writable: true,\n },\n\n /**\n * Keep track of which trajectories are currently drawn.\n */\n renderedTrajectories: {\n get: () => (this.tracker && this.tracker.renderedTrajectories) || [],\n },\n\n /**\n * Id of the hovered vehicle.\n */\n hoverVehicleId: {\n value: hoverVehicleId,\n writable: true,\n },\n\n /**\n * Id of the selected vehicle.\n */\n selectedVehicleId: {\n value: selectedVehicleId,\n writable: true,\n },\n\n /**\n * Id of the selected vehicle.\n */\n pixelRatio: {\n value:\n pixelRatio ||\n (typeof window !== 'undefined' ? window.devicePixelRatio : 1),\n writable: true,\n },\n\n /**\n * Options used by the constructor of the Tracker class.\n */\n initTrackerOptions: {\n value: initTrackerOptions,\n writable: false,\n },\n\n /**\n * If true, encapsulates the renderTrajectories calls in a requestAnimationFrame.\n */\n useRequestAnimationFrame: {\n value: options.useRequestAnimationFrame || false,\n writable: true,\n },\n\n /**\n * If true, encapsulates the renderTrajectories calls in a throttle function. Default to true.\n */\n useThrottle: {\n value: options.useThrottle || true,\n writable: true,\n },\n\n /**\n * If true, encapsulates the renderTrajectories calls in a debounce function.\n */\n useDebounce: {\n value: options.useDebounce || false,\n writable: true,\n },\n\n /**\n * Filter properties used in combination with permalink parameters.\n */\n publishedLineName: {\n get: () => publishedLineName,\n set: (newPublishedLineName) => {\n publishedLineName = newPublishedLineName;\n this.updateFilters();\n },\n },\n tripNumber: {\n get: () => tripNumber,\n set: (newTripNumber) => {\n tripNumber = newTripNumber;\n this.updateFilters();\n },\n },\n operator: {\n get: () => operator,\n set: (newOperator) => {\n operator = newOperator;\n this.updateFilters();\n },\n },\n regexPublishedLineName: {\n get: () => regexPublishedLineName,\n set: (newRegex) => {\n regexPublishedLineName = newRegex;\n this.updateFilters();\n },\n },\n\n /**\n * Style properties.\n */\n delayDisplay: {\n value: options.delayDisplay || 300000,\n writable: true,\n },\n delayOutlineColor: {\n value: options.delayOutlineColor || '#000000',\n writable: true,\n },\n\n /**\n * Debug properties.\n */\n // Not used anymore, but could be useful for debugging.\n // showVehicleTraj: {\n // value:\n // options.showVehicleTraj !== undefined\n // ? options.showVehicleTraj\n // : true,\n // writable: true,\n // },\n });\n\n // Update filter function based on convenient properties\n this.updateFilters();\n }\n\n init(map) {\n super.init(map);\n\n this.tracker = new Tracker({\n style: (...args) => this.style(...args),\n ...this.initTrackerOptions,\n });\n\n // If the layer is visible we start the rendering clock\n if (this.visible) {\n this.start();\n }\n\n // On change of visibility we start/stop the rendering clock\n this.visibilityRef = this.on('change:visible', (evt) => {\n if (evt.target.visible) {\n this.start();\n } else {\n this.stop();\n }\n });\n\n // To avoid browser hanging when the tab is not visible for a certain amount of time,\n // We stop the rendering and the websocket when hide and start again when show.\n document.addEventListener(\n 'visibilitychange',\n this.onDocumentVisibilityChange,\n );\n }\n\n terminate() {\n document.removeEventListener(\n 'visibilitychange',\n this.onDocumentVisibilityChange,\n );\n\n this.stop();\n unByKey(this.visibilityRef);\n if (this.tracker) {\n const { canvas } = this.tracker;\n const context = canvas.getContext('2d');\n context.clearRect(0, 0, canvas.width, canvas.height);\n this.tracker = null;\n }\n super.terminate();\n }\n\n start() {\n this.stop();\n this.renderTrajectories();\n this.startUpdateTime();\n\n if (this.isClickActive) {\n this.onClick(this.onFeatureClick);\n }\n\n if (this.isHoverActive) {\n this.onHover(this.onFeatureHover);\n }\n\n this.api.open();\n this.api.subscribeTrajectory(\n this.mode,\n this.onTrajectoryMessage,\n this.isUpdateBboxOnMoveEnd,\n );\n this.api.subscribeDeletedVehicles(\n this.mode,\n this.onDeleteTrajectoryMessage,\n this.isUpdateBboxOnMoveEnd,\n );\n\n if (this.isUpdateBboxOnMoveEnd) {\n // Update the bbox on each move end\n this.setBbox();\n }\n }\n\n /**\n * Start the clock.\n * @private\n */\n startUpdateTime() {\n this.stopUpdateTime();\n this.updateTimeDelay = this.getRefreshTimeInMs();\n this.updateTimeInterval = setInterval(() => {\n // When live=true, we update the time with new Date();\n this.time = this.live\n ? new Date()\n : this.time.getTime() + this.updateTimeDelay * this.speed;\n }, this.updateTimeDelay);\n }\n\n stop() {\n this.api.unsubscribeTrajectory(this.onTrajectoryMessage);\n this.api.unsubscribeDeletedVehicles(this.onDeleteTrajectoryMessage);\n this.api.close();\n }\n\n /**\n * Stop the clock.\n * @private\n */\n stopUpdateTime() {\n if (this.updateTimeInterval) {\n clearInterval(this.updateTimeInterval);\n }\n }\n\n /**\n * Launch renderTrajectories. it avoids duplicating code in renderTrajectories method.\n *\n * @param {object} viewState The view state of the map.\n * @param {number[2]} viewState.center Center coordinate of the map in mercator coordinate.\n * @param {number[4]} viewState.extent Extent of the map in mercator coordinates.\n * @param {number[2]} viewState.size Size ([width, height]) of the canvas to render.\n * @param {number} [viewState.rotation = 0] Rotation of the map to render.\n * @param {number} viewState.resolution Resolution of the map to render.\n * @param {boolean} noInterpolate If true trajectories are not interpolated but\n * drawn at the last known coordinate. Use this for performance optimization\n * during map navigation.\n * @private\n */\n renderTrajectoriesInternal(viewState, noInterpolate) {\n if (!this.tracker) {\n return false;\n }\n\n const time = this.live ? Date.now() : this.time;\n\n const trajectories = Object.values(this.trajectories);\n\n // console.time('sort');\n if (this.sort) {\n trajectories.sort(this.sort);\n }\n // console.timeEnd('sort');\n\n // console.time('render');\n this.renderState = this.tracker.renderTrajectories(\n trajectories,\n { ...viewState, pixelRatio: this.pixelRatio, time },\n {\n noInterpolate:\n viewState.zoom < this.minZoomInterpolation ? true : noInterpolate,\n hoverVehicleId: this.hoverVehicleId,\n selectedVehicleId: this.selectedVehicleId,\n iconScale: this.iconScale,\n delayDisplay: this.delayDisplay,\n delayOutlineColor: this.delayOutlineColor,\n },\n );\n\n // console.timeEnd('render');\n return true;\n }\n\n /**\n * Render the trajectories requesting an animation frame and cancelling the previous one.\n * This function must be overrided by children to provide the correct parameters.\n *\n * @param {object} viewState The view state of the map.\n * @param {number[2]} viewState.center Center coordinate of the map in mercator coordinate.\n * @param {number[4]} viewState.extent Extent of the map in mercator coordinates.\n * @param {number[2]} viewState.size Size ([width, height]) of the canvas to render.\n * @param {number} [viewState.rotation = 0] Rotation of the map to render.\n * @param {number} viewState.resolution Resolution of the map to render.\n * @param {boolean} noInterpolate If true trajectories are not interpolated but\n * drawn at the last known coordinate. Use this for performance optimization\n * during map navigation.\n * @private\n */\n renderTrajectories(viewState, noInterpolate) {\n if (this.requestId) {\n cancelAnimationFrame(this.requestId);\n this.requestId = null;\n }\n\n if (!noInterpolate && this.useRequestAnimationFrame) {\n this.requestId = requestAnimationFrame(() => {\n this.renderTrajectoriesInternal(viewState, noInterpolate);\n });\n } else if (!noInterpolate && this.useDebounce) {\n this.debounceRenderTrajectories(viewState, noInterpolate);\n } else if (!noInterpolate && this.useThrottle) {\n this.throttleRenderTrajectories(viewState, noInterpolate);\n } else {\n this.renderTrajectoriesInternal(viewState, noInterpolate);\n }\n }\n\n setBbox(extent, zoom) {\n // Clean trajectories before sending the new bbox\n // Purge trajectories:\n // - which are outside the extent\n // - when it's bus and zoom level is too low for them\n const keys = Object.keys(this.trajectories);\n for (let i = keys.length - 1; i >= 0; i -= 1) {\n this.purgeTrajectory(this.trajectories[keys[i]], extent, zoom);\n }\n\n const bbox = [...extent];\n\n if (this.isUpdateBboxOnMoveEnd) {\n bbox.push(zoom);\n\n if (this.tenant) {\n bbox.push(`tenant=${this.tenant}`);\n }\n\n /* @ignore */\n this.generalizationLevel = this.generalizationLevelByZoom[zoom];\n if (this.generalizationLevel) {\n bbox.push(`gen=${this.generalizationLevel}`);\n }\n }\n\n this.api.bbox = bbox;\n }\n\n setMode(mode) {\n if (this.mode === mode) {\n return;\n }\n this.mode = mode;\n this.api.subscribeTrajectory(\n this.mode,\n this.onTrajectoryMessage,\n this.isUpdateBboxOnMoveEnd,\n );\n this.api.subscribeDeletedVehicles(\n this.mode,\n this.onDeleteTrajectoryMessage,\n this.isUpdateBboxOnMoveEnd,\n );\n }\n\n /**\n * Get the duration before the next update depending on zoom level.\n *\n * @private\n * @param {number} zoom\n */\n getRefreshTimeInMs(zoom) {\n const roundedZoom = Math.round(zoom);\n const timeStep = timeSteps[roundedZoom] || 25;\n const nextTick = Math.max(25, timeStep / this.speed);\n const nextThrottleTick = Math.min(nextTick, 500);\n // TODO: see if this should go elsewhere.\n if (this.useThrottle) {\n this.throttleRenderTrajectories = throttle(\n this.renderTrajectoriesInternal,\n nextThrottleTick,\n { leading: true, trailing: true },\n );\n } else if (this.useDebounce) {\n this.debounceRenderTrajectories = debounce(\n this.renderTrajectoriesInternal,\n nextThrottleTick,\n { leading: true, trailing: true, maxWait: 5000 },\n );\n }\n if (this.api?.buffer) {\n const [, size] = this.api.buffer;\n this.api.buffer = [nextThrottleTick, size];\n }\n return nextTick;\n }\n\n /**\n * Get vehicle.\n * @param {function} filterFc A function use to filter results.\n * @return {Array<Object>} Array of vehicle.\n */\n getVehicle(filterFc) {\n return Object.values(this.trajectories).filter(filterFc);\n }\n\n /**\n * Request feature information for a given coordinate.\n *\n * @param {ol/coordinate~Coordinate} coordinate Coordinate.\n * @param {Object} options Options See child classes to see which options are supported.\n * @param {number} [options.resolution=1] The resolution of the map.\n * @param {number} [options.nb=Infinity] The max number of vehicles to return.\n * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.\n */\n getFeatureInfoAtCoordinate(coordinate, options = {}) {\n const { resolution, nb } = options;\n const ext = buffer(\n [...coordinate, ...coordinate],\n this.hitTolerance * resolution,\n );\n let trajectories = Object.values(this.trajectories);\n\n if (this.sort) {\n trajectories = trajectories.sort(this.sort);\n }\n\n const vehicles = [];\n for (let i = 0; i < trajectories.length; i += 1) {\n if (\n trajectories[i].properties.coordinate &&\n containsCoordinate(ext, trajectories[i].properties.coordinate)\n ) {\n vehicles.push(trajectories[i]);\n }\n if (vehicles.length === nb) {\n break;\n }\n }\n\n return Promise.resolve({\n layer: this,\n features: vehicles.map((vehicle) => this.format.readFeature(vehicle)),\n coordinate,\n });\n }\n\n /**\n * Request the stopSequence and the fullTrajectory informations for a vehicle.\n *\n * @param {string} id The vehicle identifier (the train_id property).\n * @return {Promise<{stopSequence: StopSequence, fullTrajectory: FullTrajectory>} A promise that will be resolved with the trajectory informations.\n */\n getTrajectoryInfos(id) {\n // When a vehicle is selected, we request the complete stop sequence and the complete full trajectory.\n // Then we combine them in one response and send them to inherited layers.\n const promises = [\n this.api.getStopSequence(id, this.mode),\n this.api.getFullTrajectory(id, this.mode, this.generalizationLevel),\n ];\n\n return Promise.all(promises).then(([stopSequence, fullTrajectory]) => {\n const response = {\n stopSequence,\n fullTrajectory,\n };\n return response;\n });\n }\n\n /**\n * Determine if the trajectory is useless and should be removed from the list or not.\n * By default, this function exclude vehicles:\n * - that have their trajectory outside the current extent and\n * - that are not a train and zoom level is lower than layer's minZoomNonTrain property.\n *\n * @param {TralisTrajectory} trajectory\n * @param {Array<number>} extent\n * @param {number} zoom\n * @return {boolean} if the trajectory must be displayed or not.\n * @ignore\n */\n purgeTrajectory(trajectory, extent, zoom) {\n const { type, bounds, train_id: id } = trajectory.properties;\n if (\n !intersects(extent, bounds) ||\n (type !== 'rail' && zoom < (this.minZoomNonTrain || 9))\n ) {\n this.removeTrajectory(id);\n return true;\n }\n return false;\n }\n\n /**\n * Add a trajectory to the tracker.\n * @param {TralisTrajectory} trajectory The trajectory to add.\n * @private\n */\n addTrajectory(trajectory) {\n if (this.filter && !this.filter(trajectory)) {\n return;\n }\n this.trajectories[trajectory.properties.train_id] = trajectory;\n this.renderTrajectories();\n }\n\n removeTrajectory(id) {\n delete this.trajectories[id];\n }\n\n /**\n * On zoomend we adjust the time interval of the update of vehicles positions.\n *\n * @param evt Event that triggered the function.\n * @private\n */\n // eslint-disable-next-line no-unused-vars\n onZoomEnd(evt) {\n this.startUpdateTime();\n }\n\n onDocumentVisibilityChange() {\n if (!this.visible) {\n return;\n }\n if (document.hidden) {\n this.stop();\n } else {\n this.start();\n }\n }\n\n /**\n * Callback on websocket's trajectory channel events.\n * It adds a trajectory to the list.\n *\n * @private\n */\n onTrajectoryMessage(data) {\n if (!data.content) {\n return;\n }\n const trajectory = data.content;\n\n const {\n geometry,\n properties: {\n train_id: id,\n time_since_update: timeSinceUpdate,\n raw_coordinates: rawCoordinates,\n },\n } = trajectory;\n\n // ignore old events [SBAHNM-97]\n if (timeSinceUpdate < 0) {\n return;\n }\n\n // console.time(`onTrajectoryMessage${data.content.properties.train_id}`);\n if (this.purgeTrajectory(trajectory)) {\n return;\n }\n\n if (\n this.debug &&\n this.mode === TralisModes.TOPOGRAPHIC &&\n rawCoordinates\n ) {\n trajectory.properties.olGeometry = {\n type: 'Point',\n coordinates: fromLonLat(\n rawCoordinates,\n this.map.getView().getProjection(),\n ),\n };\n } else {\n trajectory.properties.olGeometry = this.format.readGeometry(geometry);\n }\n\n // TODO Make sure the timeOffset is useful. May be we can remove it.\n trajectory.properties.timeOffset = Date.now() - data.timestamp;\n this.addTrajectory(trajectory);\n }\n\n /**\n * Callback on websocket's deleted_vehicles channel events.\n * It removes the trajectory from the list.\n *\n * @private\n * @override\n */\n onDeleteTrajectoryMessage(data) {\n if (!data.content) {\n return;\n }\n\n this.removeTrajectory(data.content);\n }\n\n /**\n * Callback when user moves the mouse/pointer over the map.\n * It sets the layer's hoverVehicleId property with the current hovered vehicle's id.\n *\n * @private\n * @override\n */\n onFeatureHover(features, layer, coordinate) {\n const [feature] = features;\n let id = null;\n if (feature) {\n id = feature.get('train_id');\n }\n if (this.hoverVehicleId !== id) {\n /** @ignore */\n this.hoverVehicleId = id;\n this.renderTrajectories(true);\n }\n }\n\n /**\n * Callback when user clicks on the map.\n * It sets the layer's selectedVehicleId property with the current selected vehicle's id.\n *\n * @private\n * @override\n */\n onFeatureClick(features, layer, coordinate) {\n const [feature] = features;\n let id = null;\n if (feature) {\n id = feature.get('train_id');\n }\n if (this.selectedVehicleId !== id) {\n /** @ignore */\n this.selectedVehicleId = id;\n this.selectedVehicle = feature;\n this.renderTrajectories(true);\n }\n }\n\n /**\n * Update filter provided by properties or permalink.\n */\n updateFilters() {\n // Setting filters from the permalink if no values defined by the layer.\n const parameters = qs.parse(window.location.search.toLowerCase());\n const publishedName = this.publishedLineName || parameters[LINE_FILTER];\n const tripNumber = this.tripNumber || parameters[ROUTE_FILTER];\n const operator = this.operator || parameters[OPERATOR_FILTER];\n const { regexPublishedLineName } = this;\n\n // Only overrides filter function if one of this property exists.\n if (publishedName || tripNumber || operator || regexPublishedLineName) {\n // filter is the property in TrackerLayerMixin.\n this.filter = createFilters(\n publishedName,\n tripNumber,\n operator,\n regexPublishedLineName,\n );\n }\n }\n };\n\nexport default TralisLayerMixin;\n","import { Style, Fill, Stroke, Circle } from 'ol/style';\nimport { getBgColor } from '../../common/trackerConfig';\n\nconst borderStyle = new Style({\n zIndex: 2,\n image: new Circle({\n radius: 5,\n fill: new Fill({\n color: '#000000',\n }),\n }),\n stroke: new Stroke({\n color: '#000000',\n width: 6,\n }),\n});\n\nconst fullTrajectorystyle = (feature) => {\n let lineColor = '#ffffff'; // white\n\n const type = feature.get('type');\n let stroke = feature.get('stroke');\n\n if (stroke && stroke[0] !== '#') {\n stroke = `#${stroke}`;\n }\n\n lineColor = stroke || getBgColor(type);\n\n // Don't allow white lines, use red instead.\n lineColor = /#ffffff/i.test(lineColor) ? '#ff0000' : lineColor;\n\n const style = [\n borderStyle,\n new Style({\n zIndex: 3,\n image: new Circle({\n radius: 4,\n fill: new Fill({\n color: lineColor,\n }),\n }),\n stroke: new Stroke({\n color: lineColor,\n width: 4,\n }),\n }),\n ];\n return style;\n};\nexport default fullTrajectorystyle;\n","import { Style, Fill, Stroke, Circle } from 'ol/style';\n\nconst stroke = new Style({\n zIndex: 2,\n image: new Circle({\n radius: 5,\n fill: new Fill({\n color: '#000000',\n }),\n }),\n stroke: new Stroke({\n color: '#000000',\n width: 6,\n }),\n});\n\nconst fill = new Style({\n zIndex: 3,\n image: new Circle({\n radius: 4,\n fill: new Fill({\n color: '#a0a0a0',\n }),\n }),\n stroke: new Stroke({\n color: '#a0a0a0',\n width: 4,\n }),\n});\n\nconst fullTrajectoryDelaystyle = () => {\n return [stroke, fill];\n};\n\nexport default fullTrajectoryDelaystyle;\n","import GeoJSON from 'ol/format/GeoJSON';\nimport { Layer as OLLayer, Group, Vector as VectorLayer } from 'ol/layer';\nimport Source from 'ol/source/Source';\nimport { composeCssTransform } from 'ol/transform';\nimport { Vector as VectorSource } from 'ol/source';\nimport Layer from './Layer';\nimport mixin from '../../common/mixins/TralisLayerMixin';\nimport { fullTrajectoryStyle } from '../styles';\n\nconst format = new GeoJSON();\n\n/**\n * Responsible for loading and display data from a Tralis service.\n *\n * @example\n * import { TralisLayer } from 'mobility-toolbox-js/ol';\n *\n * const layer = new TralisLayer({\n * url: [yourUrl],\n * apiKey: [yourApiKey],\n * });\n *\n *\n * @see <a href=\"/api/class/src/api/tralis/TralisAPI%20js~TralisAPI%20html\">TralisAPI</a>\n *\n * @extends {Layer}\n * @implements {TralisLayerInterface}\n */\nclass TralisLayer extends mixin(Layer) {\n /**\n * Constructor.\n *\n * @param {Object} options\n * @private\n */\n constructor(options = {}) {\n // We use a group to be able to add custom vector layer in extended class.\n // For example TrajservLayer use a vectorLayer to display the complete trajectory.\n super({\n ...options,\n });\n\n /** @ignore */\n this.olLayer =\n options.olLayer ||\n new Group({\n layers: [\n new VectorLayer({\n source: new VectorSource({ features: [] }),\n style: options.fullTrajectoryStyle || fullTrajectoryStyle,\n }),\n new OLLayer({\n source: new Source({}),\n render: (frameState) => {\n if (!this.tracker || !this.tracker.canvas) {\n return null;\n }\n\n if (!this.container) {\n this.container = document.createElement('div');\n this.container.style.position = 'absolute';\n this.container.style.width = '100%';\n this.container.style.height = '100%';\n this.transformContainer = document.createElement('div');\n this.transformContainer.style.position = 'absolute';\n this.transformContainer.style.width = '100%';\n this.transformContainer.style.height = '100%';\n this.container.appendChild(this.transformContainer);\n this.tracker.canvas.style.position = 'absolute';\n this.tracker.canvas.style.top = '0';\n this.tracker.canvas.style.left = '0';\n this.tracker.canvas.style.transformOrigin = 'top left';\n this.transformContainer.appendChild(this.tracker.canvas);\n }\n\n if (this.renderedViewState) {\n const { center, resolution, rotation } = frameState.viewState;\n const {\n center: renderedCenter,\n resolution: renderedResolution,\n rotation: renderedRotation,\n } = this.renderedViewState;\n\n if (renderedResolution / resolution >= 3) {\n // Avoid having really big points when zooming fast.\n const { canvas } = this.tracker;\n const context = canvas.getContext('2d');\n context.clearRect(0, 0, canvas.width, canvas.height);\n } else {\n const pixelCenterRendered =\n this.map.getPixelFromCoordinate(renderedCenter);\n const pixelCenter = this.map.getPixelFromCoordinate(center);\n this.transformContainer.style.transform = composeCssTransform(\n pixelCenterRendered[0] - pixelCenter[0],\n pixelCenterRendered[1] - pixelCenter[1],\n renderedResolution / resolution,\n renderedResolution / resolution,\n rotation - renderedRotation,\n 0,\n 0,\n );\n }\n }\n return this.container;\n },\n }),\n ],\n });\n\n // We store the layer used to highlight the full Trajectory\n this.vectorLayer = this.olLayer.getLayers().item(0);\n\n // Options the last render run did happen. If something changes\n // we have to render again\n /** @ignore */\n this.renderState = {\n center: [0, 0],\n zoom: null,\n rotation: 0,\n };\n }\n\n init(map) {\n super.init(map);\n if (this.map) {\n this.olListenersKeys.push(\n this.map.on(['moveend', 'change:target'], (evt) => {\n const view = this.map.getView();\n if (view.getAnimating() || view.getInteracting()) {\n return;\n }\n const zoom = view.getZoom();\n\n // Update the interval between render updates\n if (this.currentZoom !== zoom) {\n this.onZoomEnd(evt);\n }\n this.currentZoom = zoom;\n\n this.onMoveEnd(evt);\n }),\n );\n }\n }\n\n /**\n * Destroy the container of the tracker.\n */\n terminate() {\n super.terminate();\n this.container = null;\n }\n\n /**\n * Detect in the canvas if there is data to query at a specific coordinate.\n * @param {ol/coordinate~Coordinate} coordinate The coordinate to test\n * @returns\n */\n hasFeatureInfoAtCoordinate(coordinate) {\n if (this.map && this.tracker && this.tracker.canvas) {\n const context = this.tracker.canvas.getContext('2d');\n const pixel = this.map.getPixelFromCoordinate(coordinate);\n return !!context.getImageData(\n pixel[0] * this.pixelRatio,\n pixel[1] * this.pixelRatio,\n 1,\n 1,\n ).data[3];\n }\n return false;\n }\n\n /**\n * Render the trajectories using current map's size, resolution and rotation.\n * @param {boolean} noInterpolate if true, renders the vehicles without interpolating theirs positions.\n * @overrides\n */\n renderTrajectories(noInterpolate) {\n const view = this.map.getView();\n super.renderTrajectories(\n {\n size: this.map.getSize(),\n center: this.map.getView().getCenter(),\n extent: view.calculateExtent(),\n resolution: view.getResolution(),\n rotation: view.getRotation(),\n zoom: view.getZoom(),\n pixelRatio: this.pixelRatio,\n },\n noInterpolate,\n );\n }\n\n /**\n * Launch renderTrajectories. it avoids duplicating code in renderTrajectories methhod.\n * @private\n * @override\n */\n renderTrajectoriesInternal(viewState, noInterpolate) {\n let isRendered = false;\n\n const blockRendering =\n this.map.getView().getAnimating() || this.map.getView().getInteracting();\n\n // Don't render the map when the map is animating or interacting.\n isRendered = blockRendering\n ? false\n : super.renderTrajectoriesInternal(viewState, noInterpolate);\n\n // We update the current render state.\n if (isRendered) {\n this.renderedViewState = { ...viewState };\n\n if (this.transformContainer) {\n this.transformContainer.style.transform = '';\n }\n }\n }\n\n /**\n * Return the delay in ms before the next rendering.\n */\n getRefreshTimeInMs() {\n return super.getRefreshTimeInMs(this.map.getView().getZoom());\n }\n\n getFeatureInfoAtCoordinate(coordinate, options = {}) {\n const resolution = this.map.getView().getResolution();\n return super.getFeatureInfoAtCoordinate(coordinate, {\n resolution,\n ...options,\n });\n }\n\n /**\n * On move end we update the websocket with the new bbox.\n *\n * @param {ol/MapEvent~MapEvent} evt Moveend event\n * @private\n * @override\n */\n onMoveEnd() {\n if (this.visible && this.isUpdateBboxOnMoveEnd) {\n this.setBbox();\n }\n\n if (\n this.visible &&\n this.isUpdateBboxOnMoveEnd &&\n this.isClickActive &&\n this.selectedVehicleId\n ) {\n this.highlightTrajectory(this.selectedVehicleId);\n }\n }\n\n /**\n * Function called on moveend event only when the zoom has changed.\n *\n * @param {ol/MapEvent~MapEvent} evt Moveend event.\n * @private\n * @override\n */\n // eslint-disable-next-line no-unused-vars\n onZoomEnd(evt) {\n super.onZoomEnd(evt);\n }\n\n /**\n * Update the cursor style when hovering a vehicle.\n *\n * @private\n * @override\n */\n onFeatureHover(features, layer, coordinate) {\n super.onFeatureHover(features, layer, coordinate);\n this.map.getTargetElement().style.cursor = features.length\n ? 'pointer'\n : 'auto';\n }\n\n /**\n * Display the complete trajectory of the vehicle.\n *\n * @private\n * @override\n */\n onFeatureClick(features, layer, coordinate) {\n super.onFeatureClick(features, layer, coordinate);\n if (!features.length && this.vectorLayer) {\n this.vectorLayer.getSource().clear();\n }\n if (this.selectedVehicleId) {\n this.highlightTrajectory(this.selectedVehicleId);\n }\n }\n\n /**\n * Remove the trajectory form the list if necessary.\n *\n * @private\n */\n purgeTrajectory(trajectory, extent, zoom) {\n return super.purgeTrajectory(\n trajectory,\n extent || this.map.getView().calculateExtent(),\n zoom || this.map.getView().getZoom(),\n );\n }\n\n /**\n * Send the current bbox to the websocket\n *\n * @private\n */\n setBbox(extent, zoom) {\n let newExtent = extent;\n let newZoom = zoom;\n if (!newExtent && this.isUpdateBboxOnMoveEnd) {\n newExtent = extent || this.map.getView().calculateExtent();\n newZoom = Math.floor(this.map.getView().getZoom());\n }\n super.setBbox(newExtent, newZoom);\n }\n\n /**\n * Highlight the trajectory of journey.\n * @private\n */\n highlightTrajectory(id) {\n this.api\n .getFullTrajectory(id, this.mode, this.generalizationLevel)\n .then((fullTrajectory) => {\n const vectorSource = this.vectorLayer.getSource();\n vectorSource.clear();\n\n if (\n !fullTrajectory ||\n !fullTrajectory.features ||\n !fullTrajectory.features.length\n ) {\n return;\n }\n const features = format.readFeatures(fullTrajectory);\n this.vectorLayer.getSource().addFeatures(features);\n });\n }\n\n /**\n * Create a copy of the TralisLayer.\n * @param {Object} newOptions Options to override\n * @return {TralisLayer} A TralisLayer\n */\n clone(newOptions) {\n return new TralisLayer({ ...this.options, ...newOptions });\n }\n}\n\nexport default TralisLayer;\n","import Layer from './Layer';\n\n/**\n * A class use to display vector data.\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass VectorLayer extends Layer {\n /**\n * Request feature information for a given coordinate.\n * @param {ol/coordinate~Coordinate} coordinate the coordinate to request the information at.\n * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.\n */\n getFeatureInfoAtCoordinate(coordinate) {\n let features = [];\n\n if (this.map) {\n const pixel = this.map.getPixelFromCoordinate(coordinate);\n features = this.map.getFeaturesAtPixel(pixel, {\n layerFilter: (l) => l === this.olLayer,\n hitTolerance: this.hitTolerance,\n });\n }\n\n return Promise.resolve({\n features,\n layer: this,\n coordinate,\n });\n }\n\n /**\n * Create a copy of the VectorLayer.\n * @param {Object} newOptions Options to override\n * @return {VectorLayer} A VectorLayer\n */\n clone(newOptions) {\n return new VectorLayer({ ...this.options, ...newOptions });\n }\n}\n\nexport default VectorLayer;\n","import GeoJSON from 'ol/format/GeoJSON';\nimport Layer from './Layer';\n\n/**\n * Class use to display a WMS layer.\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass WMSLayer extends Layer {\n /**\n * @override\n */\n constructor(options = {}) {\n super(options);\n\n /** @ignore */\n this.abortController = new AbortController();\n /** @ignore */\n this.format = new GeoJSON();\n }\n\n /**\n * Get features infos' Url.\n * @param {ol/coordinate~Coordinate} coord\n * @return {ol/layer/Layer~Layer}\n */\n getFeatureInfoUrl(coord) {\n const projection = this.map.getView().getProjection();\n const resolution = this.map.getView().getResolution();\n\n if (this.olLayer.getSource().getFeatureInfoUrl) {\n return this.olLayer\n .getSource()\n .getFeatureInfoUrl(coord, resolution, projection, {\n info_format: 'application/json',\n query_layers: this.olLayer.getSource().getParams().layers,\n });\n }\n return false;\n }\n\n /**\n * Request feature information for a given coordinate.\n * @param {ol/coordinate~Coordinate} coordinate to request the information at.\n * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.\n */\n getFeatureInfoAtCoordinate(coordinate) {\n this.abortController.abort();\n this.abortController = new AbortController();\n const { signal } = this.abortController;\n return fetch(this.getFeatureInfoUrl(coordinate), { signal })\n .then((resp) => resp.json())\n .then((r) => r.features)\n .then((data) => ({\n layer: this,\n coordinate,\n features: data.map((d) => this.format.readFeature(d)),\n }))\n .catch(() =>\n // resolve an empty feature array something fails\n Promise.resolve({\n features: [],\n coordinate,\n layer: this,\n }),\n );\n }\n\n /**\n * Create a copy of the WMSLayer.\n * @param {Object} newOptions Options to override\n * @return {WMSLayer} A WMSLayer\n */\n clone(newOptions) {\n return new WMSLayer({ ...this.options, ...newOptions });\n }\n}\n\nexport default WMSLayer;\n","import BaseObject from 'ol/Object';\n\n/**\n * A class representing a control to display on map.\n *\n * @example\n * const control = new Control();\n *\n * @classproperty {ol/Map~Map|mapboxgl.Map} map - The map which the control refers to.\n * @classproperty {boolean} active - Active the control.\n * @classproperty {HTMLElement} element - The HTML element used to render the control.\n * @classproperty {HTMLElement} target - The HTML element where to render the element property. Default is the map's element. Read only.\n */\nclass Control extends BaseObject {\n /**\n * Constructor\n *\n * @param {Object} [options] Control options.\n * @param {boolean} [options.active = true] Whether the control is active or not.\n * @param {HTMLElement} [options.element] The HTML element used to render the control.\n * @param {HTMLElement} [options.target] The HTML element where to render the element property. Default is the map's element.\n * @param {function} [options.render] Render function called whenever the control needs to be rerendered.\n */\n constructor(options = {}) {\n super(options);\n this.defineProperties(options);\n\n const { active } = {\n active: options.active !== false,\n ...options,\n };\n\n /**\n * @ignore\n */\n this.active = active;\n }\n\n /**\n * Define control's properties.\n *\n * @private\n */\n defineProperties(options) {\n const { target, element, render } = {\n ...options,\n };\n\n Object.defineProperties(this, {\n active: {\n get: () => this.get('active'),\n set: (newActive) => {\n this.set('active', newActive);\n if (newActive) {\n this.activate();\n } else {\n this.deactivate();\n }\n this.render();\n },\n },\n map: {\n get: () => this.get('map'),\n set: (map) => {\n // Remove previous node.\n if (this.map && this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n }\n\n // Clean listeners\n this.deactivate();\n\n this.set('map', map);\n\n if (this.map) {\n // Add new node\n const targett =\n this.target ||\n (this.map.getTargetElement && this.map.getTargetElement()) ||\n (this.map.getContainer && this.map.getContainer());\n\n if (!this.element) {\n this.createDefaultElement();\n }\n\n if (this.element) {\n targett.appendChild(this.element);\n }\n\n // Add listeners\n if (this.active) {\n this.activate();\n }\n }\n this.render();\n },\n },\n target: {\n value: target,\n },\n element: {\n value: element,\n writable: true,\n },\n render: {\n /** @ignore */\n value: render || this.render,\n writable: true,\n },\n });\n }\n\n /**\n * Add listeners then renders the control.\n * To be defined in inherited classes.\n */\n activate() {\n this.deactivate();\n }\n\n /**\n * Remove listeners added by activate() function then renders the control.\n * To be defined in inherited classes.\n */\n // eslint-disable-next-line class-methods-use-this\n deactivate() {}\n\n /**\n * The default render function. It renders content in the HTML element.\n * To be defined in inherited classes.\n *\n * @private\n */\n render() {}\n\n /**\n * The default element to display if this.element is not defined.\n * To be defined in inherited classes.\n *\n * @private\n */\n // eslint-disable-next-line class-methods-use-this\n createDefaultElement() {}\n}\n\nexport default Control;\n","/* eslint-disable class-methods-use-this */\n/* eslint-disable max-classes-per-file */\n\n/**\n * Copyright control interface.\n *\n */\nexport class CopyrightInterface {\n /**\n * Return an array of layer's copyright.\n *\n * @return {String[]} A list of copyrights to render.\n */\n getCopyrights() {}\n}\n\n/**\n * Mixin for CopyrightInterface.\n *\n * @param {Class} Base A class to extend with {CopyrightInterface} functionnalities.\n * @return {Class} A class that implements <CopyrightInterface> class and extends Base;\n * @private\n */\nconst CopyrightMixin = (Base) =>\n class extends Base {\n render() {\n if (!this.element) {\n return;\n }\n this.element.innerHTML = this.active\n ? this.getCopyrights().join(' | ')\n : '';\n }\n\n createDefaultElement() {\n this.element = document.createElement('div');\n this.element.id = 'mbt-copyright';\n Object.assign(this.element.style, {\n position: 'absolute',\n bottom: 0,\n right: 0,\n fontSize: '.8rem',\n padding: '0 10px',\n });\n }\n };\n\nexport default CopyrightMixin;\n","import { inView } from 'ol/layer/Layer';\nimport Control from '../../common/controls/Control';\nimport mixin from '../../common/mixins/CopyrightMixin';\nimport removeDuplicate from '../../common/utils/removeDuplicate';\n\n/**\n * Display layer's copyrights.\n *\n * @example\n * import { Map } from 'ol';\n * import { CopyrightControl } from 'mobility-toolbox-js/ol';\n *\n * const map = new Map({\n * target: 'map',\n * });\n * const control = new CopyrightControl();\n * control.map = map\n *\n *\n * @see <a href=\"/example/ol-copyright\">Openlayers copyright example</a>\n *\n * @extends {Control}\n * @implements {CopyrightInterface}\n */\nclass CopyrightControl extends mixin(Control) {\n constructor(options) {\n super(options);\n this.onPostRender = this.onPostRender.bind(this);\n }\n\n getCopyrights() {\n if (!this.frameState) {\n return [];\n }\n let copyrights = [];\n\n // This code loop comes mainly from ol.\n this.frameState.layerStatesArray.forEach((layerState) => {\n const { layer } = layerState;\n if (\n inView(layerState, this.frameState.viewState) &&\n layer &&\n layer.getSource &&\n layer.getSource() &&\n layer.getSource().getAttributions()\n ) {\n copyrights = copyrights.concat(\n layer.getSource().getAttributions()(this.frameState),\n );\n }\n });\n return removeDuplicate(copyrights);\n }\n\n activate() {\n super.activate();\n if (this.map) {\n this.map.on('postrender', this.onPostRender);\n }\n }\n\n deactivate() {\n if (this.map) {\n this.map.un('postrender', this.onPostRender);\n }\n super.deactivate();\n }\n\n onPostRender(evt) {\n if (this.map && this.element) {\n /**\n * @ignore\n */\n this.frameState = evt.frameState;\n this.render();\n }\n }\n}\n\nexport default CopyrightControl;\n","/* eslint-disable no-empty-function */\n/* eslint-disable no-useless-constructor */\n/* eslint-disable class-methods-use-this */\n/* eslint-disable max-classes-per-file */\nimport StopsAPI from '../../api/stops/StopsAPI';\n\n/**\n * Search control interface.\n *\n * @classproperty {StopsSearchParams} apiParams - Default request parameters used by the search method. See [Stops service documentation](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).\n */\nexport class SearchInterface {\n /**\n * Constructor.\n *\n * @param {Object} options Map options\n * @param {string} options.apiKey Access key for [geOps services](https://developer.geops.io/). See StopsAPI.\n * @param {string} [options.url='https://api.geops.io/tracker/v1'] Stops service url. See StopsAPI.\n * @param {string} [options.placeholder='Search for a stop...'] Input field placeholder.\n * @param {StopsSearchParams} [options.apiParams={ limit: 20 }] Request parameters. See [Stops service documentation](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).\n */\n // eslint-disable-next-line no-unused-vars\n constructor(options = {}) {}\n\n /**\n * Launch a search.\n *\n * @param {String} query The query to search for.\n * @param {AbortController} abortController Abort controller used to cancel the request.\n * @return {Promise<Array<GeoJSONFeature>>} An array of GeoJSON features with coordinates in [EPSG:4326](http://epsg.io/4326).\n */\n // eslint-disable-next-line no-unused-vars\n search(query, abortController) {}\n}\n\n/**\n * Mixin for SearchInterface.\n *\n * @param {Class} Base A class to extend with {SearchInterface} functionnalities.\n * @return {Class} A class that implements <SearchInterface> class and extends Base;\n * @private\n */\nconst SearchMixin = (Base) =>\n class extends Base {\n constructor(options = {}) {\n super(options);\n const { apiParams, apiKey, url } = options;\n\n this.apiParams = { limit: 20, ...(apiParams || {}) };\n this.placeholder = options.placeholder || 'Search for a stop...';\n\n const apiOptions = { apiKey };\n if (url) {\n apiOptions.url = url;\n }\n this.api = new StopsAPI(apiOptions);\n this.abortController = new AbortController();\n }\n\n render(suggestions = []) {\n if (!this.suggestionsElt) {\n return;\n }\n\n this.suggestionsElt.style.display = suggestions.length ? 'block' : 'none';\n\n this.suggestionsElt.innerHTML = '';\n\n suggestions.forEach((suggestion) => {\n const { properties } = suggestion;\n const suggElt = document.createElement('div');\n suggElt.innerHTML = properties.name;\n suggElt.onclick = () => {\n this.onSuggestionClick(suggestion);\n };\n Object.assign(suggElt.style, {\n padding: '5px 12px',\n });\n this.suggestionsElt.appendChild(suggElt);\n });\n }\n\n createDefaultElement() {\n /**\n * Define a default element.\n */\n this.element = document.createElement('div');\n this.element.id = 'mbt-search';\n Object.assign(this.element.style, {\n position: 'absolute',\n top: 0,\n left: '50px',\n margin: '10px',\n display: 'flex',\n flexDirection: 'column',\n width: '320px',\n });\n\n // Create input element\n this.inputElt = document.createElement('input');\n this.inputElt.type = 'text';\n this.inputElt.placeholder = this.placeholder;\n this.inputElt.autoComplete = 'off';\n this.inputElt.onkeyup = (evt) => {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.search(evt.target.value, this.abortController);\n };\n Object.assign(this.inputElt.style, {\n padding: '10px 30px 10px 10px',\n });\n this.element.appendChild(this.inputElt);\n\n // Create suggestions list element\n this.suggestionsElt = document.createElement('div');\n Object.assign(this.suggestionsElt.style, {\n backgroundColor: 'white',\n overflowY: 'auto',\n cursor: 'pointer',\n });\n this.element.appendChild(this.suggestionsElt);\n\n this.clearElt = document.createElement('div');\n Object.assign(this.clearElt.style, {\n display: 'none',\n position: 'absolute',\n right: '0',\n padding: '0 10px',\n fontSize: '200%',\n cursor: 'pointer',\n });\n this.clearElt.innerHTML = '×';\n this.clearElt.onclick = () => this.clear();\n this.element.appendChild(this.clearElt);\n }\n\n search(q, abortController) {\n if (q !== undefined || q !== null) {\n this.apiParams.q = q;\n }\n\n if (this.clearElt) {\n this.clearElt.style.display = 'block';\n }\n\n return this.api\n .search(this.apiParams, abortController)\n .then((data) => {\n this.render(data);\n })\n .catch(() => {\n this.render();\n });\n }\n\n /**\n * To be defined in inherited class\n */\n // eslint-disable-next-line no-unused-vars\n onSuggestionClick(suggestion) {}\n\n /**\n * Clear the search field and close the control.\n */\n clear() {\n if (!this.suggestionsElt) {\n return;\n }\n\n this.inputElt.value = '';\n this.suggestionsElt.innerHTML = '';\n this.clearElt.style.display = 'none';\n }\n };\n\nexport default SearchMixin;\n","import { fromLonLat } from 'ol/proj';\nimport Control from '../../common/controls/Control';\nimport mixin from '../../common/mixins/SearchMixin';\n\n/**\n * Search stations.\n *\n * @example\n * import { Map } from 'ol';\n * import { StopFinderControl } from 'mobility-toolbox-js/ol';\n *\n * const map = new Map({\n * target: 'map',\n * });\n *\n * const control = new StopFinderControl({\n * apiKey: [yourApiKey]\n * });\n *\n * control.map = map;\n *\n *\n * @see <a href=\"/example/ol-search\">Openlayers search example</a>\n *\n * @extends {Control}\n * @implements {SearchInterface}\n */\nclass StopFinderControl extends mixin(Control) {\n /**\n * @private\n */\n onSuggestionClick({ geometry }) {\n const coord = fromLonLat(geometry.coordinates);\n this.map.getView().setCenter(coord);\n }\n}\n\nexport default StopFinderControl;\n","import { getWidth, getHeight } from 'ol/extent';\nimport { fromLonLat } from 'ol/proj';\n\n/**\n * Get the current resolution of a Mapbox map.\n * @param {mapboxgl.Map} map A map object.\n * @private\n */\nexport const getMercatorResolution = (map) => {\n const bounds = map.getBounds().toArray();\n const a = fromLonLat(bounds[0]);\n const b = fromLonLat(bounds[1]);\n const extent = [...a, ...b];\n const { width, height } = map.getCanvas();\n const xResolution = getWidth(extent) / width;\n const yResolution = getHeight(extent) / height;\n return Math.max(xResolution, yResolution);\n};\n\n/**\n * Get the canvas source coordinates of the current map's extent.\n * @param {mapboxgl.Map} map A map object.\n * @private\n */\nexport const getSourceCoordinates = (map, pixelRatio) => {\n // Requesting getBounds is not enough when we rotate the map, so we request manually each corner.\n const { width, height } = map.getCanvas();\n const leftTop = map.unproject({ x: 0, y: 0 });\n const leftBottom = map.unproject({ x: 0, y: height / pixelRatio }); // southWest\n const rightBottom = map.unproject({\n x: width / pixelRatio,\n y: height / pixelRatio,\n });\n const rightTop = map.unproject({ x: width / pixelRatio, y: 0 }); // north east\n return [\n [leftTop.lng, leftTop.lat],\n [rightTop.lng, rightTop.lat],\n [rightBottom.lng, rightBottom.lat],\n [leftBottom.lng, leftBottom.lat],\n ];\n};\n\nexport default {\n getMercatorResolution,\n getSourceCoordinates,\n};\n","import { fromLonLat } from 'ol/proj';\nimport { unByKey } from 'ol/Observable';\nimport { getWidth, getHeight } from 'ol/extent';\nimport transformRotate from '@turf/transform-rotate';\nimport { point } from '@turf/helpers';\nimport mixin from '../../common/mixins/TralisLayerMixin';\nimport Layer from './Layer';\nimport { getSourceCoordinates, getMercatorResolution } from '../utils';\n\n/**\n * Responsible for loading and display data from a Tralis service.\n *\n * @example\n * import { TralisLayer } from 'mobility-toolbox-js/mapbox';\n *\n * const layer = new TralisLayer({\n * url: [yourUrl],\n * apiKey: [yourApiKey],\n * });\n *\n *\n * @see <a href=\"/api/class/src/api/tralis/TralisAPI%20js~TralisAPI%20html\">TralisAPI</a>\n *\n * @extends {Layer}\n * @implements {TralisLayerInterface}\n */\nclass TralisLayer extends mixin(Layer) {\n constructor(options = {}) {\n super({\n ...options,\n });\n\n /** @ignore */\n this.onLoad = this.onLoad.bind(this);\n\n /** @ignore */\n this.onMove = this.onMove.bind(this);\n\n /** @ignore */\n this.onMoveEnd = this.onMoveEnd.bind(this);\n\n /** @ignore */\n this.onZoomEnd = this.onZoomEnd.bind(this);\n\n /** @ignore */\n this.onVisibilityChange = this.onVisibilityChange.bind(this);\n }\n\n /**\n * Initialize the layer.\n *\n * @param {mapboxgl.Map} map A [mapbox Map](https://docs.mapbox.com/mapbox-gl-js/api/map/).\n * @param {string} beforeId Layer's id before which we want to add the new layer.\n * @override\n */\n init(map, beforeId) {\n if (!map) {\n return;\n }\n\n const canvas = map.getCanvas();\n\n super.init(map, {\n width: canvas.width / this.pixelRatio,\n height: canvas.height / this.pixelRatio,\n });\n\n this.source = {\n type: 'canvas',\n canvas: this.tracker.canvas,\n coordinates: getSourceCoordinates(map, this.pixelRatio),\n // Set to true if the canvas source is animated. If the canvas is static, animate should be set to false to improve performance.\n animate: true,\n attribution: this.copyrights && this.copyrights.join(', '),\n };\n\n this.beforeId = beforeId;\n this.layer = {\n id: this.key,\n type: 'raster',\n source: this.key,\n layout: {\n visibility: this.visible ? 'visible' : 'none',\n },\n paint: {\n 'raster-opacity': 1,\n 'raster-fade-duration': 0,\n 'raster-resampling': 'nearest', // important otherwise it looks blurry\n },\n };\n\n if (map.isStyleLoaded()) {\n this.onLoad();\n }\n\n this.map.on('load', this.onLoad);\n\n this.listeners = [this.on('change:visible', this.onVisibilityChange)];\n }\n\n /**\n * Remove listeners from the Mapbox Map.\n */\n terminate() {\n if (this.map) {\n this.map.off('load', this.onLoad);\n\n this.listeners.forEach((listener) => {\n unByKey(listener);\n });\n if (this.map.getLayer(this.key)) {\n this.map.removeLayer(this.key);\n }\n if (this.map.getSource(this.key)) {\n this.map.removeSource(this.key);\n }\n }\n super.terminate();\n }\n\n /**\n * Start updating vehicles position.\n *\n * @listens {mapboxgl.map.event:zoomend} Listen to zoom end event.\n * @listens {mapboxgl.map.event:mousemove} Listen to mousemove end.\n * @override\n */\n start() {\n super.start();\n\n this.map.on('move', this.onMove);\n this.map.on('moveend', this.onMoveEnd);\n this.map.on('zoomend', this.onZoomEnd);\n }\n\n /**\n * Stop updating vehicles position, and unlisten events.\n *\n * @override\n */\n stop() {\n super.stop();\n if (this.map) {\n this.map.off('move', this.onMove);\n this.map.off('moveend', this.onMoveEnd);\n this.map.off('zoomend', this.onZoomEnd);\n }\n }\n\n onLoad() {\n if (!this.map.getSource(this.key)) {\n this.map.addSource(this.key, this.source);\n }\n if (!this.map.getLayer(this.key)) {\n this.map.addLayer(this.layer, this.beforeId);\n }\n }\n\n /**\n * Function triggered when the user click the map.\n * @override\n */\n onUserClickCallback(evt) {\n super.onUserClickCallback({\n coordinate: fromLonLat(evt.lngLat.toArray()),\n ...evt,\n });\n }\n\n /**\n * Function triggered when the user moves the cursor over the map.\n * @override\n */\n onUserMoveCallback(evt) {\n super.onUserMoveCallback({\n coordinate: fromLonLat(evt.lngLat.toArray()),\n ...evt,\n });\n }\n\n /**\n * Render the trajectories using current map's size, resolution and rotation.\n * @param {boolean} noInterpolate if true, renders the vehicles without interpolating theirs positions.\n * @overrides\n */\n renderTrajectories(noInterpolate) {\n const { width, height } = this.map.getCanvas();\n const center = this.map.getCenter();\n\n // We use turf here to have good transform.\n const leftBottom = this.map.unproject({\n x: 0,\n y: height / this.pixelRatio,\n }); // southWest\n const rightTop = this.map.unproject({ x: width / this.pixelRatio, y: 0 }); // north east\n\n const coord0 = transformRotate(\n point([leftBottom.lng, leftBottom.lat]),\n -this.map.getBearing(),\n {\n pivot: [center.lng, center.lat],\n },\n ).geometry.coordinates;\n const coord1 = transformRotate(\n point([rightTop.lng, rightTop.lat]),\n -this.map.getBearing(),\n {\n pivot: [center.lng, center.lat],\n },\n ).geometry.coordinates;\n\n const bounds = [...fromLonLat(coord0), ...fromLonLat(coord1)];\n const xResolution = getWidth(bounds) / (width / this.pixelRatio);\n const yResolution = getHeight(bounds) / (height / this.pixelRatio);\n const res = Math.max(xResolution, yResolution);\n\n // Coordinate of trajectories are in mercator so we have to pass the proper resolution and center in mercator.\n const viewState = {\n size: [width / this.pixelRatio, height / this.pixelRatio],\n center: fromLonLat([center.lng, center.lat]),\n extent: bounds,\n resolution: res,\n zoom: this.map.getZoom(),\n rotation: -(this.map.getBearing() * Math.PI) / 180,\n pixelRatio: this.pixelRatio,\n };\n\n super.renderTrajectories(viewState, noInterpolate);\n }\n\n /**\n * Return the delay in ms before the next rendering.\n */\n getRefreshTimeInMs() {\n return super.getRefreshTimeInMs(this.map.getZoom());\n }\n\n getFeatureInfoAtCoordinate(coordinate, options = {}) {\n const resolution = getMercatorResolution(this.map);\n return super.getFeatureInfoAtCoordinate(coordinate, {\n resolution,\n ...options,\n });\n }\n\n onVisibilityChange() {\n if (this.visible && !this.map.getLayer(this.key)) {\n this.map.addLayer(this.layer, this.beforeId);\n } else if (this.map.getLayer(this.key)) {\n this.map.removeLayer(this.key);\n }\n // We can't use setLayoutProperty it triggers an error probably a bug in mapbox\n // this.map.setLayoutProperty(\n // this.key,\n // 'visibilty',\n // this.visible ? 'visible' : 'none',\n // );\n }\n\n /**\n * Remove the trajectory form the list if necessary.\n *\n * @private\n */\n purgeTrajectory(trajectory, extent, zoom) {\n return super.purgeTrajectory(\n trajectory,\n extent || this.getMercatorExtent(),\n zoom || Math.floor(this.map.getZoom() + 1),\n );\n }\n\n /**\n * Send the current bbox to the websocket\n */\n setBbox(extent, zoom) {\n let newExtent = extent;\n let newZoom = zoom;\n if (!newExtent && this.isUpdateBboxOnMoveEnd) {\n newExtent = extent || this.getMercatorExtent();\n newZoom = Math.floor(this.getOlZoom());\n }\n super.setBbox(newExtent, newZoom);\n }\n\n /**\n * Callback on 'move' event.\n *\n * @private\n */\n onMove() {\n const extent = getSourceCoordinates(this.map, this.pixelRatio);\n const source = this.map.getSource(this.key);\n if (source) {\n source.setCoordinates(extent);\n }\n this.renderTrajectories();\n }\n\n /**\n * Send the new BBOX to the websocket.\n *\n * @param {ol/MapEvent~MapEvent} evt Moveend event\n * @private\n * @override\n */\n onMoveEnd() {\n this.renderTrajectories();\n\n if (this.visible && this.isUpdateBboxOnMoveEnd) {\n this.setBbox();\n }\n }\n\n /**\n * Update the cursor style when hovering a vehicle.\n *\n * @private\n * @override\n */\n onFeatureHover(features, layer, coordinate) {\n super.onFeatureHover(features, layer, coordinate);\n this.map.getCanvasContainer().style.cursor = features.length\n ? 'pointer'\n : 'auto';\n }\n}\n\nexport default TralisLayer;\n","import { unByKey } from 'ol/Observable';\nimport { transformExtent } from 'ol/proj';\nimport LayerCommon from '../../common/layers/Layer';\n\n/**\n * A class representing a layer to display on an OpenLayers map.\n *\n * @example\n * import { Layer } from 'mobility-toolbox-js/ol';\n *\n * const layer = new Layer({\n * olLayer: ...,\n * });\n *\n * @see <a href=\"/example/ol-map\">Map example</a>\n *\n * @classproperty {ol/Map~Map} map - The map where the layer is displayed.\n * @extends {Layer}\n */\nclass Layer extends LayerCommon {\n /**\n * Initialize the layer and listen to user events.\n * @param {ol/Map~Map} map\n */\n init(map) {\n super.init(map);\n\n if (!this.map) {\n return;\n }\n\n if (this.isClickActive || this.isHoverActive) {\n this.toggleVisibleListeners();\n this.onChangeVisibleKey = this.on(\n 'change:visible',\n this.toggleVisibleListeners,\n );\n }\n }\n\n terminate(map) {\n if (this.map) {\n this.map.off('mousemove', this.onUserMoveCallback);\n this.map.off('click', this.onUserClickCallback);\n unByKey(this.onChangeVisibleKey);\n }\n super.terminate(map);\n }\n\n /**\n * Function triggered when the user click the map.\n * @private\n */\n onUserClickCallback(evt) {\n super.onUserClickCallback({ coordinate: evt.lngLat.toArray(), ...evt });\n }\n\n /**\n * Function triggered when the user moves the cursor over the map.\n * @private\n */\n onUserMoveCallback(evt) {\n super.onUserMoveCallback({ coordinate: evt.lngLat.toArray(), ...evt });\n }\n\n /**\n * Toggle listeners needed when a layer is avisible or not.\n * @private\n */\n toggleVisibleListeners() {\n if (this.visible) {\n if (this.isClickActive) {\n this.map.on('click', this.onUserClickCallback);\n }\n\n if (this.isHoverActive) {\n this.map.on('mousemove', this.onUserMoveCallback);\n }\n } else {\n if (this.isClickActive) {\n this.map.off('click', this.onUserClickCallback);\n }\n\n if (this.isHoverActive) {\n this.map.off('mousemove', this.onUserMoveCallback);\n }\n }\n }\n\n /**\n * Returns the current extent in mercator coordinates.\n */\n getMercatorExtent() {\n const bounds = this.map.getBounds().toArray();\n return transformExtent(\n [...bounds[0], ...bounds[1]],\n 'EPSG:4326',\n 'EPSG:3857',\n );\n }\n\n /**\n * Returns the equivalent zoom in Openlayers.\n */\n getOlZoom() {\n return this.map.getZoom() + 1;\n }\n\n /**\n * Create a copy of the Layer.\n * @param {Object} newOptions Options to override\n * @return {Layer} A Layer\n */\n clone(newOptions) {\n return new Layer({ ...this.options, ...newOptions });\n }\n}\nexport default Layer;\n","import Control from '../../common/controls/Control';\nimport mixin from '../../common/mixins/CopyrightMixin';\nimport { getMapboxMapCopyrights } from '../../common/utils';\n\n/**\n * Display layer's copyrights.\n *\n * @example\n * import { Map } from 'mapbox-gl';\n * import { CopyrightControl } from 'mobility-toolbox-js/mapbox';\n *\n * const map = new Map({\n * container: 'map',\n * style: `https://maps.geops.io/styles/travic_v2/style.json?key=${window.apiKey}`,\n * controls: [\n * new CopyrightControl()\n * ]\n * });\n *\n * const control = new CopyrightControl();\n * control.map = map;\n *\n *\n * @see <a href=\"/example/mb-copyright\">Mapbox copyright example</a>\n *\n * @extends {Control}\n * @implements {CopyrightInterface}\n */\nclass CopyrightControl extends mixin(Control) {\n constructor(options) {\n super(options);\n this.render = this.render.bind(this);\n }\n\n activate() {\n super.activate();\n if (this.map) {\n this.map.on('sourcedata', this.render);\n this.map.on('styledata', this.render);\n this.map.on('idle', this.render);\n }\n }\n\n deactivate() {\n if (this.map) {\n this.map.off('sourcedata', this.render);\n this.map.off('styledata', this.render);\n this.map.off('idle', this.render);\n }\n super.deactivate();\n }\n\n getCopyrights() {\n return getMapboxMapCopyrights(this.map);\n }\n}\n\nexport default CopyrightControl;\n","import {\n Layer as olLayer,\n WMSLayer as olWMSLayer,\n MapboxLayer as olMapboxLayer,\n TralisLayer as olTralisLayer,\n VectorLayer as olVectorLayer,\n} from './ol';\nimport { TralisLayer as mbTralisLayer } from './mapbox';\n\nconst exports = {\n mapbox: {\n TralisLayer: mbTralisLayer,\n },\n ol: {\n Layer: olLayer,\n WMSLayer: olWMSLayer,\n MapboxLayer: olMapboxLayer,\n TralisLayer: olTralisLayer,\n VectorLayer: olVectorLayer,\n },\n};\n\nexport default exports;\n"],"sourceRoot":""}