WME Route Speeds (MapOMatic fork)

Shows segment speeds in a route.

  1. // ==UserScript==
  2. // @name WME Route Speeds (MapOMatic fork)
  3. // @description Shows segment speeds in a route.
  4. // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor\/?.*$/
  5. // @version 2025.01.13.000
  6. // @grant GM_xmlhttpRequest
  7. // @namespace https://greatest.deepsurf.us/en/scripts/369630-wme-route-speeds-mapomatic-fork
  8. // @require https://greatest.deepsurf.us/scripts/24851-wazewrap/code/WazeWrap.js
  9. // @author wlodek76 (forked by MapOMatic)
  10. // @copyright 2014, 2015 wlodek76
  11. // @contributor 2014, 2015 FZ69617
  12. // @connect greatest.deepsurf.us
  13. // ==/UserScript==
  14.  
  15. /* global W */
  16. /* global OpenLayers */
  17.  
  18. /* eslint-disable */
  19. (function () {
  20. "use strict";
  21.  
  22. const DOWNLOAD_URL = 'https://update.greatest.deepsurf.us/scripts/369630/WME%20Route%20Speeds%20%28MapOMatic%20fork%29.user.js';
  23. const SCRIPT_VERSION = GM_info.script.version.toString();
  24. const SCRIPT_NAME = GM_info.script.name;
  25.  
  26. const KM_PER_MILE = 1.609344;
  27.  
  28. const SAVED_OPTIONS_KEY = "RouteSpeedsOptions";
  29. const options = {
  30. enableScript: true,
  31. showLabels: true,
  32. showSpeeds: true,
  33. useMiles: false,
  34. showRouteText: false,
  35. getAlternatives: true,
  36. maxRoutes: 3,
  37. liveTraffic: true,
  38. routingOrder: true,
  39. useRBS: false,
  40. routeType: 1,
  41. vehicleType: 'PRIVATE',
  42. avoidTolls: false,
  43. avoidFreeways: false,
  44. avoidDifficult: false,
  45. avoidFerries: false,
  46. avoidUnpaved: true,
  47. avoidLongUnpaved: false,
  48. allowUTurns: true,
  49. passes: []
  50. };
  51.  
  52. let countryPassList = [];
  53.  
  54. var wmech_version = GM_info.script.version;
  55.  
  56. var epsg900913;
  57. var epsg4326;
  58.  
  59. var selected = 0;
  60.  
  61. var routesReceived = [];
  62. var routesShown = [];
  63.  
  64. var routewait = 0;
  65. var routeSelected = 0;
  66. var routeSelectedLast = -1;
  67.  
  68. var markerA;
  69. var markerB;
  70. var markerA_offset_click = [0, 0];
  71. var markerB_offset_click = [0, 0];
  72.  
  73. var lastmapcenter = [0, 0];
  74. var panningX = 0;
  75. var panningY = 0;
  76. var acceleration = 1.6;
  77. var accelerationmin = 10;
  78. var accelerationmax = 200;
  79. var accelerationmargin = 30;
  80. var accelerationbackstop = 3;
  81.  
  82. const INVALID_SPEED_COLOR = '#808080';
  83. const METRIC_SPEED_COLORS = [
  84. '#2e131c', // < 5.5 km/h
  85. '#711422', // < 10.5 km/h
  86. '#af0b26', // < 15.5 km/h
  87. '#e9052a', // < 20.5 km/h
  88. '#ff632a', // < 30.5 km/h
  89. '#ffab20', // < 40.5 km/h
  90. '#ffd60f', // < 50.5 km/h
  91. '#9ce30b', // < 60.5 km/h
  92. '#23bf4c', // < 70.5 km/h
  93. '#32c6c2', // < 80.5 km/h
  94. '#09d7ff', // < 90.5 km/h
  95. '#09a9ff', // < 100.5 km/h
  96. '#1555fe', // < 110.5 km/h
  97. '#5e00e0', // < 120.5 km/h
  98. '#a504cd', // < 130.5 km/h
  99. '#851680', // < 140.5 km/h
  100. '#531947' // >= 140.5 km/h
  101. ];
  102. const IMPERIAL_SPEED_COLORS = [
  103. '#2e131c', // < 3.5 mph
  104. '#711422', // < 6.5 mph
  105. '#af0b26', // < 9.5 mph
  106. '#e9052a', // < 12.5 mph
  107. '#ff492a', // < 15.5 mph
  108. '#ff7b28', // < 20.5 mph
  109. '#ffab20', // < 25.5 mph
  110. '#ffd60f', // < 30.5 mph
  111. '#9ce30b', // < 35.5 mph
  112. '#04d02e', // < 40.5 mph
  113. '#2cae60', // < 45.5 mph
  114. '#32c6c2', // < 50.5 mph
  115. '#09d7ff', // < 55.5 mph
  116. '#09a9ff', // < 60.5 mph
  117. '#0d75ff', // < 65.5 mph
  118. '#1b2fff', // < 70.5 mph
  119. '#5e00e0', // < 75.5 mph
  120. '#a504cd', // < 80.5 mph
  121. '#851680', // < 85.5 mph
  122. '#531947' // >= 85.5 mph
  123. ];
  124.  
  125. const ROUTE_COLORS = [
  126. '#4d4dcd', // route 1
  127. '#d34f8a', // route 2
  128. '#188984', // route 3
  129. '#cafa27', // route 4
  130. '#ffca3f', // route 5
  131. '#39e440', // route 6
  132. '#a848e2', // route 7
  133. '#cbbf00', // route 8
  134. '#2994f3', // route 9
  135. '#ff3d1e', // route 10
  136. '#b0b7f8', // route 11
  137. '#ffb0ba', // route 12
  138. '#71ded2', // route 13
  139. '#86c211', // route 14
  140. '#ff8500', // route 15
  141. '#00a842', // route 16
  142. '#ecd4ff', // route 17
  143. '#7c00ff', // route 18
  144. '#caeeff', // route 19
  145. '#ffdab8' // route 20
  146. ];
  147.  
  148. var jqueryinfo = 0;
  149. var tabswitched = 0;
  150. var leftHand = false;
  151.  
  152. const SCRIPT_LAYERS_TO_COVER = ["_LTHighlightLayer", "LTLaneGraphics", "LTNamesLayer"];
  153. const WME_LAYERS_TO_MOVE = ["closures", "turn_closure", "closure_nodes"];
  154. let layersMoved = [];
  155. let originalZIndexes = [];
  156. let baseZIndex = 0;
  157. let z17_reached = 0;
  158.  
  159. function log(msg) {
  160. console.log('WME Route Speeds:', msg);
  161. }
  162.  
  163. async function onWmeReady(tries = 0) {
  164. if (WazeWrap && WazeWrap.Ready) {
  165. startScriptUpdateMonitor();
  166. log('Initializing...');
  167. await initialiseWMERouteSpeeds();
  168. log(wmech_version + " loaded.");
  169. } else {
  170. if (tries === 0) {
  171. log('Waiting for WazeWrap...');
  172. } else if (tries === 300) {
  173. console.error('WME Route Speeds:', 'WazeWrap loading failed. Giving up.');
  174. return;
  175. }
  176. setTimeout(onWmeReady, 100, ++tries);
  177. }
  178. }
  179.  
  180. function startScriptUpdateMonitor() {
  181. log('Checking for script updates...');
  182. let updateMonitor;
  183. try {
  184. updateMonitor = new WazeWrap.Alerts.ScriptUpdateMonitor(SCRIPT_NAME, SCRIPT_VERSION, DOWNLOAD_URL, GM_xmlhttpRequest);
  185. updateMonitor.start();
  186. } catch (ex) {
  187. // Report, but don't stop if ScriptUpdateMonitor fails.
  188. console.error(SCRIPT_NAME, ex);
  189. }
  190. }
  191.  
  192. function bootstrap() {
  193. log('Waiting for WME...');
  194. if (typeof W === 'object' && W.userscripts?.state.isReady) {
  195. onWmeReady();
  196. } else {
  197. document.addEventListener('wme-ready', onWmeReady, { once: true });
  198. }
  199. }
  200.  
  201. //------------------------------------------------------------------------------------------------
  202. function panningWMERouteSpeeds() {
  203. var WM = W.map;
  204.  
  205. //var operationPending = W.vent._events.listeners.operationPending[0];
  206. //if (operationPending == undefined) return;
  207. //var pending = operationPending.obj.pending[0];
  208.  
  209. //var lastcenterX = lastmapcenter[0];
  210. //var lastcenterY = lastmapcenter[1];
  211. //var centerX = WM.getCenter().lon;
  212. //var centerY = WM.getCenter().lat;
  213.  
  214. //if (lastcenterX == 0) lastcenterX = centerX;
  215. //if (lastcenterY == 0) lastcenterY = centerY;
  216.  
  217. //if ( lastcenterX==centerX && lastcenterY==centerY && pending == undefined ) {
  218. if (panningX || panningY) {
  219. var accelX = panningX;
  220. var accelY = panningY;
  221.  
  222. if (accelX < 0) accelX = -Math.pow(Math.abs(accelX), acceleration) - accelerationmin;
  223. if (accelX > 0) accelX = Math.pow(Math.abs(accelX), acceleration) + accelerationmin;
  224.  
  225. if (accelY < 0) accelY = -Math.pow(Math.abs(accelY), acceleration) - accelerationmin;
  226. if (accelY > 0) accelY = Math.pow(Math.abs(accelY), acceleration) + accelerationmin;
  227.  
  228. if (accelX < -accelerationmax) accelX = -accelerationmax;
  229. if (accelY < -accelerationmax) accelY = -accelerationmax;
  230. if (accelX > accelerationmax) accelX = accelerationmax;
  231. if (accelY > accelerationmax) accelY = accelerationmax;
  232.  
  233. WM.getOLMap().pan(accelX, accelY);
  234. }
  235. //}
  236. }
  237. //------------------------------------------------------------------------------------------------
  238. function saveRouteSpeedsOptions() {
  239.  
  240. localStorage.setItem(SAVED_OPTIONS_KEY, JSON.stringify(options));
  241.  
  242. }
  243. //---------------------------------------------------------------------------------------
  244. function loadRouteSpeedsOptions() {
  245.  
  246. try {
  247. Object.assign(options, JSON.parse(localStorage.getItem(SAVED_OPTIONS_KEY)));
  248. } catch {
  249. log("Error loading saved options. Using defaults.");
  250. }
  251.  
  252. getId('routespeeds-enablescript').checked = options.enableScript;
  253. getId('routespeeds-showLabels').checked = options.showLabels;
  254. getId('routespeeds-showSpeeds').checked = options.showSpeeds;
  255. getId('routespeeds-usemiles').checked = options.useMiles;
  256. getId('routespeeds-routetext').checked = options.showRouteText;
  257. getId('routespeeds-getalternatives').checked = options.getAlternatives;
  258. getId('routespeeds-maxroutes').value = options.maxRoutes;
  259. getId('routespeeds-livetraffic').checked = options.liveTraffic;
  260. getId('routespeeds-avoidtolls').checked = options.avoidTolls;
  261. getId('routespeeds-avoidfreeways').checked = options.avoidFreeways;
  262. getId('routespeeds-avoidunpaved').checked = options.avoidUnpaved;
  263. getId('routespeeds-avoidlongunpaved').checked = options.avoidLongUnpaved;
  264. getId('routespeeds-routetype').value = options.routeType;
  265. getId('routespeeds-allowuturns').checked = options.allowUTurns;
  266. getId('routespeeds-routingorder').checked = options.routingOrder;
  267. getId('routespeeds-userbs').checked = options.useRBS;
  268. getId('routespeeds-avoiddifficult').checked = options.avoidDifficult;
  269. getId('routespeeds-avoidferries').checked = options.avoidFerries;
  270. getId('routespeeds-vehicletype').value = options.vehicleType;
  271. }
  272. //---------------------------------------------------------------------------------------
  273. function getRoutingManager() {
  274. if (W.model.countries.getObjectById(235) || W.model.countries.getObjectById(40) || W.model.countries.getObjectById(182)) { // US, Canada, & PR
  275. return '/RoutingManager/routingRequest';
  276. } else if (W.model.countries.getObjectById(106)) { // Israel
  277. return '/il-RoutingManager/routingRequest';
  278. } else {
  279. return '/row-RoutingManager/routingRequest'; // ROW
  280. }
  281. }
  282. //------------------------------------------------------------------------------------------------
  283. function getSegmentMidPoint(seg, end) {
  284.  
  285. var points, p1, p2, dx, dy, x, y;
  286. var olGeo = W.userscripts.toOLGeometry(seg.getGeometry());
  287. points = olGeo.components.length;
  288.  
  289. if (points == 2) {
  290. p1 = olGeo.components[0];
  291. p2 = olGeo.components[1];
  292.  
  293. x = p1.x + (p2.x - p1.x) * 0.5;
  294. y = p1.y + (p2.y - p1.y) * 0.5;
  295. return OpenLayers.Layer.SphericalMercator.inverseMercator(x, y);
  296. }
  297.  
  298. var length = 0;
  299. for (var i = 0; i < points - 1; i++) {
  300. p1 = olGeo.components[i + 0];
  301. p2 = olGeo.components[i + 1];
  302. dx = p2.x - p1.x;
  303. dy = p2.y - p1.y;
  304. length += Math.sqrt(dx * dx + dy * dy);
  305. }
  306. var midlen = length / 2.0;
  307.  
  308. var length1 = 0;
  309. var length2 = 0;
  310. for (i = 0; i < points - 1; i++) {
  311. p1 = olGeo.components[i + 0];
  312. p2 = olGeo.components[i + 1];
  313. dx = p2.x - p1.x;
  314. dy = p2.y - p1.y;
  315. length1 = length2;
  316. length2 = length2 + Math.sqrt(dx * dx + dy * dy);
  317.  
  318. if (midlen >= length1 && midlen < length2) {
  319. var proc = (midlen - length1) / (length2 - length1);
  320. x = p1.x + (p2.x - p1.x) * proc;
  321. y = p1.y + (p2.y - p1.y) * proc;
  322. return OpenLayers.Layer.SphericalMercator.inverseMercator(x, y);
  323. }
  324. }
  325.  
  326. if (end === 0) {
  327. p1 = olGeo.components[0];
  328. p2 = olGeo.components[1];
  329. }
  330. else {
  331. p1 = olGeo.components[points - 2];
  332. p2 = olGeo.components[points - 1];
  333. }
  334.  
  335. x = p1.x + (p2.x - p1.x) * 0.5;
  336. y = p1.y + (p2.y - p1.y) * 0.5;
  337. return OpenLayers.Layer.SphericalMercator.inverseMercator(x, y);
  338. }
  339. //------------------------------------------------------------------------------------------------
  340. function getLabelTime(segmentInfo) {
  341. let time = 0;
  342. if (options.liveTraffic) time += segmentInfo.crossTime;
  343. else time += segmentInfo.crossTimeWithoutRealTime;
  344. return time;
  345. }
  346. //------------------------------------------------------------------------------------------------
  347. function getLabelWeight(segmentInfo) {
  348. if (options.liveTraffic && segmentInfo.crossTime != segmentInfo.crossTimeWithoutRealTime) return 'bold';
  349. else return 'normal';
  350. }
  351. //------------------------------------------------------------------------------------------------
  352. function getLabelColor(segmentInfo) {
  353. if (options.liveTraffic) {
  354. if (segmentInfo.crossTime != segmentInfo.crossTimeWithoutRealTime) {
  355. let ratio = segmentInfo.crossTime / segmentInfo.crossTimeWithoutRealTime;
  356. if (ratio > 2) return '#ff0000';
  357. if (ratio > 1.25) return '#ff9900';
  358. if (ratio >= 0.8) return '#ffff00';
  359. if (ratio >= 0.5) return '#99ee00';
  360. else return '#00bb33';
  361. } else {
  362. return '#f8f8f8';
  363. }
  364. } else {
  365. return '#f8f8f8';
  366. }
  367. }
  368. //------------------------------------------------------------------------------------------------
  369. function getSpeed(length_m, time_s) {
  370. if (time_s == 0) return 0;
  371. if (options.useMiles) return 3.6 * length_m / (time_s * KM_PER_MILE);
  372. else return 3.6 * length_m / time_s;
  373. }
  374. //-----------------------------------------------------------------------------------------------
  375. function getSpeedColor(speed) {
  376. if (speed === 0) return INVALID_SPEED_COLOR;
  377. let s = Math.round(speed);
  378. if (options.useMiles) {
  379. if (s <= 15) return IMPERIAL_SPEED_COLORS[Math.min(Math.ceil(s / 3) - 1, IMPERIAL_SPEED_COLORS.length - 1)];
  380. else return IMPERIAL_SPEED_COLORS[Math.min(Math.ceil(s / 5) + 1, IMPERIAL_SPEED_COLORS.length - 1)];
  381. } else {
  382. if (s <= 20) return METRIC_SPEED_COLORS[Math.min(Math.ceil(s / 5) - 1, METRIC_SPEED_COLORS.length - 1)];
  383. else return METRIC_SPEED_COLORS[Math.min(Math.ceil(s / 10) + 1, METRIC_SPEED_COLORS.length - 1)];
  384. }
  385. }
  386. //-----------------------------------------------------------------------------------------------
  387. function getRouteColor(routeNo) {
  388. let i = routeNo % ROUTE_COLORS.length;
  389. return ROUTE_COLORS[i];
  390. }
  391. //-----------------------------------------------------------------------------------------------
  392. function getTimeText(time_s) {
  393. let seconds = time_s % 60;
  394. let minutes = Math.floor((time_s % 3600) / 60);
  395. let hours = Math.floor(time_s / 3600);
  396. return String(hours).padStart(2, '0') + ':' + String(minutes).padStart(2, '0') + ':' + String(seconds).padStart(2, '0');
  397. }
  398. //-----------------------------------------------------------------------------------------------
  399. function updatePassesLabel() {
  400. let count = countryPassList.filter(pass => options.passes.indexOf(pass.key) > -1).length;
  401. $('#routespeeds-passes-label').text(`Passes & Permits (${count} of ${countryPassList.length})`);
  402. }
  403. //------------------------------------------------------------------------------------------------
  404. function addLabel(lines, segmentInfo) {
  405.  
  406. let labelText;
  407. if (options.showSpeeds) {
  408. let speed = getSpeed(segmentInfo.length, getLabelTime(segmentInfo));
  409. if (speed >= 1) labelText = Math.round(speed);
  410. else if (speed == 0) labelText = '?';
  411. else labelText = '<1';
  412. } else {
  413. labelText = getLabelTime(segmentInfo) + 's';
  414. }
  415.  
  416. var p1, p2, pt, textFeature, k, sx, sy;
  417. var numlines = lines.length;
  418. if (numlines >= 2) {
  419. var line;
  420. var ps = parseInt(numlines) >> 1;
  421. p1 = lines[ps].components[0];
  422. p2 = lines[ps].components[1];
  423. var proc = 0.5;
  424.  
  425. var dist = [];
  426. var dsum = 0;
  427. for (k = 0; k < numlines; k++) {
  428. line = lines[k];
  429. var d = line.getGeodesicLength(epsg900913);
  430. dsum += d;
  431. dist.push(d);
  432. }
  433. var dmid = dsum / 2.0;
  434. var d1 = 0;
  435. var d2 = 0;
  436. for (k = 0; k < numlines; k++) {
  437. line = lines[k];
  438. d1 = d2;
  439. d2 += dist[k];
  440. if (dmid >= d1 && dmid < d2) {
  441. p1 = lines[k].components[0];
  442. p2 = lines[k].components[1];
  443. proc = (dmid - d1) / (d2 - d1);
  444. }
  445. }
  446.  
  447. sx = p1.x + (p2.x - p1.x) * proc;
  448. sy = p1.y + (p2.y - p1.y) * proc;
  449.  
  450. pt = new OpenLayers.Geometry.Point(sx, sy);
  451. textFeature = new OpenLayers.Feature.Vector(pt, { labelText: labelText, fontWeight: getLabelWeight(segmentInfo), fontColor: getLabelColor(segmentInfo), pointRadius: 0, segmentID: segmentInfo.path.segmentId });
  452. return textFeature;
  453. }
  454. else if (numlines == 1) {
  455. p1 = lines[0].components[0];
  456. p2 = lines[0].components[1];
  457.  
  458. sx = (p1.x + p2.x) * 0.5;
  459. sy = (p1.y + p2.y) * 0.5;
  460.  
  461. pt = new OpenLayers.Geometry.Point(sx, sy);
  462. textFeature = new OpenLayers.Feature.Vector(pt, { labelText: labelText, fontWeight: getLabelWeight(segmentInfo), fontColor: getLabelColor(segmentInfo), pointRadius: 0, segmentID: segmentInfo.path.segmentId });
  463. return textFeature;
  464. }
  465. else return null;
  466. }
  467. //------------------------------------------------------------------------------------------------
  468. function panmap(draggingobj, x, y) {
  469. let viewPortDiv = draggingobj.map.getViewport();
  470. let maxX = viewPortDiv.clientWidth;
  471. let maxY = viewPortDiv.clientHeight;
  472. let lastx = draggingobj.last.x;
  473. let lasty = draggingobj.last.y;
  474. let mx = x - lastx;
  475. let my = y - lasty;
  476.  
  477. if (x < accelerationmargin) {
  478. if (mx < 0) panningX = x - accelerationmargin;
  479. if (mx > accelerationbackstop) panningX = 0;
  480. }
  481. else if (x > maxX - accelerationmargin) {
  482. if (mx > 0) panningX = x - (maxX - accelerationmargin);
  483. if (mx < -accelerationbackstop) panningX = 0;
  484. }
  485. else panningX = 0;
  486.  
  487. if (y < accelerationmargin) {
  488. if (my < 0) panningY = y - (accelerationmargin);
  489. if (my > accelerationbackstop) panningY = 0;
  490. }
  491. else if (y > maxY - accelerationmargin - 25) {
  492. if (my > 0) panningY = y - (maxY - accelerationmargin - 25);
  493. if (my < -accelerationbackstop) panningY = 0;
  494. }
  495. else panningY = 0;
  496. }
  497. //------------------------------------------------------------------------------------------------
  498. function createMarkers(lon1, lat1, lon2, lat2, disp) {
  499.  
  500. var WM = W.map;
  501.  
  502. var mlayers = WM.getLayersBy("uniqueName", "__DrawRouteSpeedsMarkers");
  503. var markerLayer = mlayers[0];
  504. var p1, p2, lonlat;
  505.  
  506. if (markerA === undefined && markerB === undefined) {
  507. var di = WazeWrap.Require.DivIcon;
  508. var iconA = new di("routespeedsmarkerA");
  509. var iconB = new di("routespeedsmarkerB");
  510.  
  511. p1 = new OpenLayers.Geometry.Point(lon1, lat1).transform(epsg4326, epsg900913);
  512. p2 = new OpenLayers.Geometry.Point(lon2, lat2).transform(epsg4326, epsg900913);
  513.  
  514. var lonlatA = new OpenLayers.LonLat(p1.x, p1.y);
  515. var lonlatB = new OpenLayers.LonLat(p2.x, p2.y);
  516.  
  517. markerA = new OpenLayers.Marker(lonlatA, iconA);
  518. markerB = new OpenLayers.Marker(lonlatB, iconB);
  519.  
  520. var wh = WazeWrap.Require.DragElement();//require("Waze/Handler/DragElement");
  521. markerA.dragging = new wh(WM);
  522. markerB.dragging = new wh(WM);
  523.  
  524. markerA.dragging.down = function (e) {
  525. lonlat = this.map.getOLMap().getLonLatFromViewPortPx(e.xy ?? e);
  526. if (lonlat === null) return;
  527. markerA_offset_click[0] = markerA.lonlat.lon - lonlat.lon;
  528. markerA_offset_click[1] = markerA.lonlat.lat - lonlat.lat;
  529. };
  530. markerB.dragging.down = function (e) {
  531. lonlat = this.map.getOLMap().getLonLatFromViewPortPx(e.xy ?? e);
  532. if (lonlat === null) return;
  533. markerB_offset_click[0] = markerB.lonlat.lon - lonlat.lon;
  534. markerB_offset_click[1] = markerB.lonlat.lat - lonlat.lat;
  535. };
  536.  
  537. markerA.dragging.move = function (e) {
  538. lonlat = this.map.getOLMap().getLonLatFromViewPortPx(e.xy);
  539. markerA.lonlat.lon = lonlat.lon + markerA_offset_click[0];
  540. markerA.lonlat.lat = lonlat.lat + markerA_offset_click[1];
  541. markerLayer.drawMarker(markerA);
  542. panmap(this, e.xy.x, e.xy.y);
  543. };
  544. markerB.dragging.move = function (e) {
  545. lonlat = this.map.getOLMap().getLonLatFromViewPortPx(e.xy);
  546. markerB.lonlat.lon = lonlat.lon + markerB_offset_click[0];
  547. markerB.lonlat.lat = lonlat.lat + markerB_offset_click[1];
  548. markerLayer.drawMarker(markerB);
  549. panmap(this, e.xy.x, e.xy.y);
  550. };
  551.  
  552. markerA.dragging.done = function (e) {
  553.  
  554. if (!options.enableScript) return;
  555.  
  556. panningX = 0;
  557. panningY = 0;
  558.  
  559. var lonlatA = new OpenLayers.LonLat(markerA.lonlat.lon, markerA.lonlat.lat).transform(epsg900913, epsg4326);
  560. var lonlatB = new OpenLayers.LonLat(markerB.lonlat.lon, markerB.lonlat.lat).transform(epsg900913, epsg4326);
  561.  
  562. lon1 = parseInt(lonlatA.lon * 1000000.0 + 0.5) / 1000000.0;
  563. lat1 = parseInt(lonlatA.lat * 1000000.0 + 0.5) / 1000000.0;
  564. lon2 = parseInt(lonlatB.lon * 1000000.0 + 0.5) / 1000000.0;
  565. lat2 = parseInt(lonlatB.lat * 1000000.0 + 0.5) / 1000000.0;
  566.  
  567. if (getId('sidepanel-routespeeds-a') !== undefined) {
  568. getId('sidepanel-routespeeds-a').value = lon1 + ", " + lat1;
  569. getId('sidepanel-routespeeds-b').value = lon2 + ", " + lat2;
  570. }
  571.  
  572. var objprog1 = getId('routespeeds-button-livemap');
  573. if (objprog1.style.backgroundColor === '') objprog1.style.backgroundColor = '#FF8000';
  574.  
  575. requestRouteFromLiveMap(lon1, lat1, lon2, lat2);
  576. };
  577. markerB.dragging.done = function (e) {
  578.  
  579. if (!options.enableScript) return;
  580.  
  581. panningX = 0;
  582. panningY = 0;
  583.  
  584. var lonlatA = new OpenLayers.LonLat(markerA.lonlat.lon, markerA.lonlat.lat).transform(epsg900913, epsg4326);
  585. var lonlatB = new OpenLayers.LonLat(markerB.lonlat.lon, markerB.lonlat.lat).transform(epsg900913, epsg4326);
  586.  
  587. lon1 = parseInt(lonlatA.lon * 1000000.0 + 0.5) / 1000000.0;
  588. lat1 = parseInt(lonlatA.lat * 1000000.0 + 0.5) / 1000000.0;
  589. lon2 = parseInt(lonlatB.lon * 1000000.0 + 0.5) / 1000000.0;
  590. lat2 = parseInt(lonlatB.lat * 1000000.0 + 0.5) / 1000000.0;
  591.  
  592. if (getId('sidepanel-routespeeds-a') !== undefined) {
  593. getId('sidepanel-routespeeds-a').value = lon1 + ", " + lat1;
  594. getId('sidepanel-routespeeds-b').value = lon2 + ", " + lat2;
  595. }
  596.  
  597. var objprog1 = getId('routespeeds-button-livemap');
  598. if (objprog1.style.backgroundColor === '') objprog1.style.backgroundColor = '#FF8000';
  599.  
  600. requestRouteFromLiveMap(lon1, lat1, lon2, lat2);
  601. };
  602.  
  603. markerA.dragging.activate(iconA.$div);
  604. markerB.dragging.activate(iconB.$div);
  605.  
  606. markerA.display(disp);
  607. markerB.display(disp);
  608.  
  609. markerLayer.addMarker(markerA);
  610. markerLayer.addMarker(markerB);
  611. }
  612. else {
  613. p1 = new OpenLayers.Geometry.Point(lon1, lat1).transform(epsg4326, epsg900913);
  614. p2 = new OpenLayers.Geometry.Point(lon2, lat2).transform(epsg4326, epsg900913);
  615.  
  616. markerA.lonlat.lon = p1.x;
  617. markerA.lonlat.lat = p1.y;
  618. markerB.lonlat.lon = p2.x;
  619. markerB.lonlat.lat = p2.y;
  620.  
  621. markerA.display(disp);
  622. markerB.display(disp);
  623.  
  624. markerLayer.drawMarker(markerA);
  625. markerLayer.drawMarker(markerB);
  626. }
  627.  
  628. markerA.created = disp;
  629. markerB.created = disp;
  630. }
  631. //------------------------------------------------------------------------------------------------
  632. function showRouteLayer(disp) {
  633. var routeLayer = W.map.getLayersBy("uniqueName", "__DrawRouteSpeedsLines")[0];
  634. if (routeLayer === undefined) return;
  635. routeLayer.setVisibility(disp);
  636. }
  637. //--------------------------------------------------------------------------------------------------------
  638. function showMarkers(disp) {
  639. var WM = W.map;
  640.  
  641. var mlayers = WM.getLayersBy("uniqueName", "__DrawRouteSpeedsMarkers");
  642. var markerLayer = mlayers[0];
  643.  
  644. if (markerLayer === undefined) return false;
  645. if (markerA === undefined) return false;
  646. if (markerB === undefined) return false;
  647.  
  648. if (markerA.created) markerA.display(disp);
  649. if (markerB.created) markerB.display(disp);
  650.  
  651. return (markerA.created && markerB.created);
  652. }
  653. //------------------------------------------------------------------------------------------------
  654. function reverseMarkers() {
  655. var WM = W.map;
  656.  
  657. var mlayers = WM.getLayersBy("uniqueName", "__DrawRouteSpeedsMarkers");
  658. var markerLayer = mlayers[0];
  659.  
  660. if (markerLayer === undefined) return;
  661. if (markerA === undefined || !markerA.created) return;
  662. if (markerB === undefined || !markerB.created) return;
  663.  
  664. var copy = markerA.lonlat;
  665. markerA.lonlat = markerB.lonlat;
  666. markerB.lonlat = copy;
  667.  
  668. markerLayer.drawMarker(markerA);
  669. markerLayer.drawMarker(markerB);
  670. }
  671. //------------------------------------------------------------------------------------------------
  672. function loopWMERouteSpeeds() {
  673.  
  674. if (!options.enableScript) return;
  675.  
  676. var tabOpen = $('#user-tabs #routespeeds-tab-label').parent().parent().attr('aria-expanded') == "true";
  677. if (!tabOpen) {
  678. if (tabswitched !== 1) {
  679. tabswitched = 1;
  680. showRouteLayer(false);
  681. showMarkers(false);
  682. reorderLayers(0);
  683. }
  684. return;
  685. }
  686. else {
  687. if (tabswitched !== 2) {
  688. tabswitched = 2;
  689. showRouteLayer(true);
  690. showMarkers(true);
  691. reorderLayers(1);
  692. }
  693. }
  694.  
  695. //var routespeedsbutton = getId('routespeeds-button-livemap');
  696. //if (routespeedsbutton == 'undefined') return;
  697. //var routespeedsbutton_ofsW = routespeedsbutton.offsetWidth;
  698. //var routespeedsbutton_ofsH = routespeedsbutton.offsetHeight;
  699. //console.log(routespeedsbutton_ofsW, routespeedsbutton_ofsH);
  700. //if (routespeedsbutton_ofsW == 0 || routespeedsbutton_ofsH==0) return;
  701.  
  702.  
  703. var WM = W.map;
  704.  
  705. var rlayers = WM.getLayersBy("uniqueName", "__DrawRouteSpeedsLines");
  706. if (rlayers.length === 0) {
  707.  
  708. var drc_style = new OpenLayers.Style({
  709. strokeDashstyle: 'solid',
  710. strokeColor: "${strokeColor}",
  711. strokeOpacity: 1.0,
  712. strokeWidth: "${strokeWidth}",
  713. fillColor: '#0040FF',
  714. fillOpacity: 1.0,
  715. pointRadius: "${pointRadius}",
  716. label: "${labelText}",
  717. fontFamily: "Tahoma, Courier New",
  718. fontWeight: "${fontWeight}",
  719. labelOutlineColor: '#404040',
  720. labelOutlineWidth: 2,
  721. fontColor: "${fontColor}",
  722. fontOpacity: 1.0,
  723. fontSize: "10px",
  724. display: 'block'
  725. });
  726.  
  727. var drc_mapLayer = new OpenLayers.Layer.Vector("Route Speeds Lines", {
  728. displayInLayerSwitcher: true,
  729. uniqueName: "__DrawRouteSpeedsLines",
  730. styleMap: new OpenLayers.StyleMap(drc_style)
  731. });
  732.  
  733. I18n.translations[I18n.currentLocale()].layers.name["__DrawRouteSpeedsLines"] = "Route Speeds Lines";
  734. drc_mapLayer.setVisibility(true);
  735. WM.addLayer(drc_mapLayer);
  736.  
  737. return;
  738. }
  739.  
  740. var mlayers = WM.getLayersBy("uniqueName", "__DrawRouteSpeedsMarkers");
  741. if (mlayers.length === 0) {
  742.  
  743. var drc_mapLayer = new OpenLayers.Layer.Markers("Route Speeds Markers", {
  744. displayInLayerSwitcher: false,
  745. uniqueName: "__DrawRouteSpeedsMarkers"
  746. });
  747.  
  748. I18n.translations[I18n.currentLocale()].layers.name["__DrawRouteSpeedsMarkers"] = "Route Speeds Markers";
  749. WM.addLayer(drc_mapLayer);
  750. drc_mapLayer.setVisibility(true);
  751.  
  752. createMarkers(16, 52, 17, 53, false);
  753.  
  754. return;
  755. }
  756.  
  757. if (jqueryinfo === 1) {
  758. jqueryinfo = 2;
  759. console.log('WME Route Speeds: jQuery reloaded ver. ' + jQuery.fn.jquery);
  760. }
  761. if (jqueryinfo === 0) {
  762. if (typeof jQuery === 'undefined') {
  763. console.log('WME Route Speeds: jQuery current ver. ' + jQuery.fn.jquery);
  764.  
  765. var script = document.createElement('script');
  766. script.type = "text/javascript";
  767. script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js";
  768. //script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
  769. document.getElementsByTagName('head')[0].appendChild(script);
  770. jqueryinfo = 1;
  771. }
  772. }
  773.  
  774.  
  775. var rlayers = WM.getLayersBy("uniqueName", "__DrawRouteSpeedsLines");
  776. var routeLayer = rlayers[0];
  777. if (routeLayer === undefined) return;
  778.  
  779. var numSelected = WazeWrap.getSelectedDataModelObjects().length;
  780. var seg1 = WazeWrap.getSelectedDataModelObjects()[0];
  781. var seg2 = WazeWrap.getSelectedDataModelObjects()[1];
  782.  
  783. if (seg1 !== undefined && seg2 !== undefined) {
  784. if (!selected) {
  785. selected = 1;
  786.  
  787. var coords1 = getSegmentMidPoint(seg1, 0);
  788. var coords2 = getSegmentMidPoint(seg2, 1);
  789.  
  790. var lon1 = parseInt(coords1.lon * 1000000.0 + 0.5) / 1000000.0;
  791. var lat1 = parseInt(coords1.lat * 1000000.0 + 0.5) / 1000000.0;
  792. var lon2 = parseInt(coords2.lon * 1000000.0 + 0.5) / 1000000.0;
  793. var lat2 = parseInt(coords2.lat * 1000000.0 + 0.5) / 1000000.0;
  794.  
  795. if (getId('sidepanel-routespeeds-a') !== undefined) {
  796. getId('sidepanel-routespeeds-a').value = lon1 + ", " + lat1;
  797. getId('sidepanel-routespeeds-b').value = lon2 + ", " + lat2;
  798. }
  799.  
  800. createMarkers(lon1, lat1, lon2, lat2, true);
  801.  
  802. leftHand = false;
  803. if (W.model.isLeftHand) leftHand = true;
  804. if (W.model.isLeftHand) leftHand = true;
  805.  
  806. requestRouteFromLiveMap(lon1, lat1, lon2, lat2);
  807. }
  808. }
  809. else {
  810. if (seg1 !== undefined || seg2 !== undefined) {
  811. if (selected) {
  812. selected = 0;
  813.  
  814. routeLayer.removeAllFeatures();
  815.  
  816. getId('routespeeds-summaries').style.visibility = 'hidden';
  817. }
  818. }
  819. }
  820.  
  821. if (!z17_reached) {
  822. if (W.map.getZoom() >= 17) {
  823. z17_reached = 1;
  824. switchRoute();
  825. }
  826. }
  827. }
  828. //--------------------------------------------------------------------------------------------------------
  829. function createRouteFeatures(id, routewsp, routeodc) {
  830.  
  831. var WM = W.map;
  832.  
  833. var rlayers = WM.getLayersBy("uniqueName", "__DrawRouteSpeedsLines");
  834. var routeLayer = rlayers[0];
  835. if (routeLayer === undefined) return;
  836.  
  837. var lineFeatures = [];
  838. var labelFeatures = [];
  839. var lines = [];
  840. var outlinepoints = [];
  841.  
  842. var segmentID = 0;
  843. var odc = 0;
  844.  
  845. segmentID = routeodc[odc].path.segmentId;
  846. var odclen = routeodc[odc].length;
  847. var odctime = getLabelTime(routeodc[odc]);
  848. var odcx = 0;
  849. var odcy = 0;
  850. if (odc + 1 < routeodc.length) {
  851. odcx = routeodc[odc + 1].path.x;
  852. odcy = routeodc[odc + 1].path.y;
  853. }
  854.  
  855. var speedColor = getSpeedColor(getSpeed(odclen, odctime));
  856.  
  857. var ptA = new OpenLayers.Geometry.Point(0, 0);
  858. var ptB = new OpenLayers.Geometry.Point(0, 0);
  859.  
  860. var doubletraffic = false;
  861. var p1 = null;
  862. var p2 = null;
  863. var doublepoints = {};
  864. var wsp1, wsp2, dlon, dlat, dx, dy, label, len, i;
  865.  
  866.  
  867. //wykrycie czy trasa przechodzi dwa razy przez te same punkty, jeżeli tak to rysowanie trasy z odstępem, aby był widoczny przebieg trasy
  868. //(detection whether the route passes through the same points twice, if so drawing the route with a gap to make the route visible)
  869. for (i = 0; i < routewsp.length - 1; i++) {
  870. wsp1 = routewsp[i + 0];
  871. wsp2 = routewsp[i + 1];
  872.  
  873. dlon = Math.abs(wsp1.x - wsp2.x);
  874. dlat = Math.abs(wsp1.y - wsp2.y);
  875.  
  876. if (dlon < 0.0000001 && dlat < 0.0000001) continue;
  877.  
  878. var s1 = parseInt(wsp1.x * 10000000 + 0.5) + ',' + parseInt(wsp1.y * 10000000 + 0.5);
  879. var s2 = parseInt(wsp2.x * 10000000 + 0.5) + ',' + parseInt(wsp2.y * 10000000 + 0.5);
  880.  
  881. if (s1 === s2) continue;
  882.  
  883. if (doublepoints[s1] === undefined) doublepoints[s1] = 0;
  884. if (doublepoints[s2] === undefined) doublepoints[s2] = 0;
  885. doublepoints[s1]++;
  886. doublepoints[s2]++;
  887.  
  888. if (doublepoints[s2] >= 2) {
  889. doubletraffic = true;
  890. break;
  891. }
  892. }
  893.  
  894. var doubletrafficoffset = 0;
  895. if (doubletraffic) {
  896. doubletrafficoffset = 11 * Math.pow(2.0, 17 - W.map.getZoom());
  897. }
  898.  
  899.  
  900. for (i = 0; i < routewsp.length - 1; i++) {
  901. wsp1 = routewsp[i + 0];
  902. wsp2 = routewsp[i + 1];
  903.  
  904. if (i === 0) {
  905. ptA.x = wsp1.x;
  906. ptA.y = wsp1.y;
  907. ptA = ptA.transform(epsg4326, epsg900913);
  908. //var p = new drc_OpenLayers.Geometry.Point(wsp1.x, wsp1.y).transform(epsg4326, epsg900913);
  909. //var pt = new drc_OpenLayers.Geometry.Point(p.x, p.y);
  910. //var textFeature = new drc_OpenLayers.Feature.Vector( ptA, {labelText: "A", pointRadius: 8, fontColor: '#FFFFFF' } );
  911. //labelFeatures.push(textFeature);
  912. }
  913. if (i === routewsp.length - 2) {
  914. ptB.x = wsp2.x;
  915. ptB.y = wsp2.y;
  916. ptB = ptB.transform(epsg4326, epsg900913);
  917. //var p = new drc_OpenLayers.Geometry.Point(wsp2.x, wsp2.y).transform(epsg4326, epsg900913);
  918. //var pt = new drc_OpenLayers.Geometry.Point(p.x, p.y);
  919. //var textFeature = new drc_OpenLayers.Feature.Vector( ptB, {labelText: "B", pointRadius: 8, fontColor: '#FFFFFF' } );
  920. //labelFeatures.push(textFeature);
  921. }
  922.  
  923. dx = Math.abs(wsp1.x - odcx);
  924. dy = Math.abs(wsp1.y - odcy);
  925.  
  926. //console.log(wsp1, odcx, odcy, dx, dy);
  927.  
  928. if (dx < 0.000001 && dy < 0.000001) {
  929.  
  930. if (options.showLabels && (routeSelected == id || routeSelected == -1)) {
  931. label = addLabel(lines, routeodc[odc]);
  932. if (label !== null) {
  933. if (routeSelected == -1) routeLayer.removeFeatures(routeLayer.getFeaturesByAttribute("segmentID", segmentID));
  934. labelFeatures.push(label);
  935. }
  936. }
  937. while (lines.length > 0) lines.pop();
  938.  
  939. if (odc + 1 < routeodc.length) {
  940. odc++;
  941. segmentID = routeodc[odc].path.segmentId;
  942. odclen = routeodc[odc].length;
  943. odctime = getLabelTime(routeodc[odc]);
  944. if (odc + 1 < routeodc.length) {
  945. odcx = routeodc[odc + 1].path.x;
  946. odcy = routeodc[odc + 1].path.y;
  947. }
  948.  
  949. speedColor = getSpeedColor(getSpeed(odclen, odctime));
  950.  
  951. }
  952. }
  953.  
  954. dlon = Math.abs(wsp1.x - wsp2.x);
  955. dlat = Math.abs(wsp1.y - wsp2.y);
  956.  
  957. if (dlon < 0.0000001 && dlat < 0.0000001) continue;
  958.  
  959. var p3 = new OpenLayers.Geometry.Point(wsp1.x, wsp1.y).transform(epsg4326, epsg900913);
  960. var p4 = new OpenLayers.Geometry.Point(wsp2.x, wsp2.y).transform(epsg4326, epsg900913);
  961.  
  962. if (doubletraffic) {
  963. dx = p4.x - p3.x;
  964. dy = p4.y - p3.y;
  965. var r = Math.sqrt(dx * dx + dy * dy);
  966. var angle = Math.acos(dx / r);
  967. if (dy < 0) angle = -angle;
  968. angle = angle - 0.5 * Math.PI;
  969. if (leftHand) angle += Math.PI;
  970.  
  971. p3.x += doubletrafficoffset * Math.cos(angle) * 0.6;
  972. p3.y += doubletrafficoffset * Math.sin(angle) * 0.6;
  973. p4.x += doubletrafficoffset * Math.cos(angle) * 0.6;
  974. p4.y += doubletrafficoffset * Math.sin(angle) * 0.6;
  975.  
  976. if (p1 !== null && p2 !== null) {
  977.  
  978. var Ax = p1.x;
  979. var Ay = p1.y;
  980. var Bx = p2.x;
  981. var By = p2.y;
  982. var Cx = p3.x;
  983. var Cy = p3.y;
  984. var Dx = p4.x;
  985. var Dy = p4.y;
  986.  
  987. dx = Cx - Bx;
  988. dy = Cy - By;
  989.  
  990. var delta = Math.sqrt(dx * dx + dy * dy);
  991.  
  992. var mx = ((By - Ay) * (Dx - Cx) - (Dy - Cy) * (Bx - Ax));
  993. var my = ((Dy - Cy) * (Bx - Ax) - (By - Ay) * (Dx - Cx));
  994.  
  995. if (Math.abs(mx) > 0.000000001 && Math.abs(my) > 0.000000001 && delta > 0.1) {
  996.  
  997. var x = ((Bx - Ax) * (Dx * Cy - Dy * Cx) - (Dx - Cx) * (Bx * Ay - By * Ax)) / mx;
  998. var y = ((Dy - Cy) * (Bx * Ay - By * Ax) - (By - Ay) * (Dx * Cy - Dy * Cx)) / my;
  999.  
  1000. var dx2 = x - Bx;
  1001. var dy2 = y - By;
  1002. var delta2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
  1003.  
  1004. if (delta2 < 1000) { // checking if point of crossing is close to segments
  1005.  
  1006. len = lineFeatures.length;
  1007. if (len > 0) {
  1008. var lf = lineFeatures[len - 1];
  1009. lf.geometry.components[1].x = x;
  1010. lf.geometry.components[1].y = y;
  1011. }
  1012.  
  1013. p3.x = x;
  1014. p3.y = y;
  1015. }
  1016. }
  1017. }
  1018. }
  1019.  
  1020. outlinepoints.push(p3);
  1021. outlinepoints.push(p4);
  1022.  
  1023. let points = [];
  1024. points.push(p3);
  1025. points.push(p4);
  1026.  
  1027. let line = new OpenLayers.Geometry.LineString(points);
  1028. lines.push(line);
  1029.  
  1030. let lineFeature;
  1031. if (routeSelected == id || routeSelected == -1) {
  1032. lineFeature = new OpenLayers.Feature.Vector(line, {labelText: '', strokeWidth: 10, strokeColor: speedColor });
  1033. } else {
  1034. lineFeature = new OpenLayers.Feature.Vector(line, {labelText: '', strokeWidth: 5, strokeColor: getRouteColor(id) });
  1035. }
  1036.  
  1037. lineFeatures.push(lineFeature);
  1038.  
  1039. p1 = p3;
  1040. p2 = p4;
  1041. }
  1042.  
  1043. if (options.showLabels && (routeSelected == id || routeSelected == -1)) {
  1044. label = addLabel(lines, routeodc[odc]);
  1045. if (label !== null) {
  1046. if (routeSelected == -1) routeLayer.removeFeatures(routeLayer.getFeaturesByAttribute("segmentID", segmentID));
  1047. labelFeatures.push(label);
  1048. }
  1049. }
  1050. while (lines.length > 0) lines.pop();
  1051.  
  1052. let outlinestring = new OpenLayers.Geometry.LineString(outlinepoints);
  1053. let outlineFeature = new OpenLayers.Feature.Vector(outlinestring, { labelText: '', strokeWidth: 12, strokeColor: '#404040' });
  1054. if (routeSelected == id || routeSelected == -1) routeLayer.addFeatures(outlineFeature);
  1055.  
  1056. routeLayer.addFeatures(lineFeatures);
  1057. routeLayer.addFeatures(labelFeatures);
  1058. //showRouteLayer(true);
  1059. }
  1060. //--------------------------------------------------------------------------------------------------------
  1061. function getElementsByClassName(classname, node) {
  1062. if (!node) node = document.getElementsByTagName("body")[0];
  1063. var a = [];
  1064. var re = new RegExp('\\b' + classname + '\\b');
  1065. var els = node.getElementsByTagName("*");
  1066. for (var i = 0, j = els.length; i < j; i++)
  1067. if (re.test(els[i].className)) a.push(els[i]);
  1068. return a;
  1069. }
  1070. //--------------------------------------------------------------------------------------------------------
  1071. function getId(node) {
  1072. return document.getElementById(node);
  1073. }
  1074. //--------------------------------------------------------------------------------------------------------
  1075. function getnowtoday() {
  1076. let hour = getId('routespeeds-hour').value;
  1077. let day = getId('routespeeds-day').value;
  1078. if (hour === '---') hour = 'now';
  1079. if (day === '---') day = 'today';
  1080. if (hour === '') hour = 'now';
  1081. if (day === '') day = 'today';
  1082.  
  1083. let t = new Date();
  1084. let thour = (t.getHours() * 60) + t.getMinutes();
  1085. let tnow = (t.getDay() * 1440) + thour;
  1086. let tsel = tnow;
  1087.  
  1088. if (hour === 'now') {
  1089. if (day === "0") tsel = (parseInt(day) * 1440) + thour;
  1090. if (day === "1") tsel = (parseInt(day) * 1440) + thour;
  1091. if (day === "2") tsel = (parseInt(day) * 1440) + thour;
  1092. if (day === "3") tsel = (parseInt(day) * 1440) + thour;
  1093. if (day === "4") tsel = (parseInt(day) * 1440) + thour;
  1094. if (day === "5") tsel = (parseInt(day) * 1440) + thour;
  1095. if (day === "6") tsel = (parseInt(day) * 1440) + thour;
  1096. }
  1097. else {
  1098. if (day === "today") tsel = (t.getDay() * 1440) + parseInt(hour);
  1099. if (day === "0") tsel = (parseInt(day) * 1440) + parseInt(hour);
  1100. if (day === "1") tsel = (parseInt(day) * 1440) + parseInt(hour);
  1101. if (day === "2") tsel = (parseInt(day) * 1440) + parseInt(hour);
  1102. if (day === "3") tsel = (parseInt(day) * 1440) + parseInt(hour);
  1103. if (day === "4") tsel = (parseInt(day) * 1440) + parseInt(hour);
  1104. if (day === "5") tsel = (parseInt(day) * 1440) + parseInt(hour);
  1105. if (day === "6") tsel = (parseInt(day) * 1440) + parseInt(hour);
  1106. }
  1107.  
  1108. //console.log(tsel, tnow, tsel-tnow);
  1109.  
  1110. return tsel - tnow;
  1111. }
  1112. //--------------------------------------------------------------------------------------------------------
  1113. function requestRouteFromLiveMap(x1, y1, x2, y2) {
  1114. var atTime = getnowtoday();
  1115.  
  1116. var numRoutes = options.getAlternatives ? 3 : 1;
  1117.  
  1118. var routeType = (options.routeType === 3) ? "TIME" : "HISTORIC_TIME";
  1119.  
  1120. var avoidTollRoads = options.avoidTolls;
  1121. var avoidPrimaries = options.avoidFreeways;
  1122. var avoidTrails = options.avoidUnpaved;
  1123. var avoidLongTrails = options.avoidLongUnpaved;
  1124. var allowUTurns = options.allowUTurns;
  1125. var avoidDifficult = options.avoidDifficult;
  1126. var avoidFerries = options.avoidFerries;
  1127. var vehType = options.vehicleType;
  1128.  
  1129. var opt = {
  1130. data: [],
  1131. add: function (name, value, defaultValue) {
  1132. if (value !== defaultValue) {
  1133. this.data.push(name + (value ? ":t" : ":f"));
  1134. }
  1135. },
  1136. put: function (name, value) {
  1137. this.data.push(name + (value ? ":t" : ":f"));
  1138. },
  1139. get: function () {
  1140. return this.data.join(",");
  1141. }
  1142. };
  1143.  
  1144. opt.add("AVOID_TOLL_ROADS", avoidTollRoads, false);
  1145. opt.add("AVOID_PRIMARIES", avoidPrimaries, false);
  1146. opt.add("AVOID_DANGEROUS_TURNS", avoidDifficult, false);
  1147. opt.add("AVOID_FERRIES", avoidFerries, false);
  1148. opt.add("ALLOW_UTURNS", allowUTurns, true);
  1149.  
  1150. if (avoidLongTrails) { opt.put("AVOID_LONG_TRAILS", true); }
  1151. else if (avoidTrails) { opt.put("AVOID_TRAILS", true); }
  1152. else { opt.put("AVOID_LONG_TRAILS", false); }
  1153.  
  1154.  
  1155. var url = getRoutingManager();
  1156. let expressPass = options.passes.map(key => key);
  1157. var data = {
  1158. from: "x:" + x1 + " y:" + y1,
  1159. to: "x:" + x2 + " y:" + y2,
  1160. returnJSON: true,
  1161. returnGeometries: true,
  1162. returnInstructions: true,
  1163. timeout: 60000,
  1164. at: atTime,
  1165. type: routeType,
  1166. nPaths: numRoutes,
  1167. clientVersion: '4.0.0',
  1168. options: opt.get(),
  1169. vehicleType: vehType,
  1170. subscription: expressPass
  1171. };
  1172. if (options.useRBS) data.id = "beta";
  1173.  
  1174. routewait = 1;
  1175. getId('routespeeds-error').innerHTML = "";
  1176.  
  1177. console.time('WME Route Speeds: routing time');
  1178.  
  1179. $.ajax({
  1180. dataType: "json",
  1181. cache: false,
  1182. url: url,
  1183. data: data,
  1184. traditional: true,
  1185. dataFilter: function (data, dataType) {
  1186. return data.replace(/NaN/g, '0');
  1187. },
  1188. error: function (req, textStatus, errorThrown) {
  1189. let str = "Route request failed" + (textStatus !== null ? " with " + textStatus : "") + "!";
  1190. str += "<br>" + errorThrown;
  1191. handleRouteRequestError(str);
  1192. },
  1193. success: function (json) {
  1194. if (json.error !== undefined) {
  1195. let str = json.error;
  1196. str = str.replace("|", "<br>");
  1197. handleRouteRequestError(str);
  1198. } else {
  1199.  
  1200. if (json.coords !== undefined) {
  1201. log("1 route received (" + numRoutes + " requested)");
  1202.  
  1203. if (routeSelected > 0) routeSelected = 0;
  1204.  
  1205. routesReceived = [json];
  1206. }
  1207. if (json.alternatives !== undefined) {
  1208. log(json.alternatives.length + " routes received (" + numRoutes + " requested)");
  1209. routesReceived = json.alternatives;
  1210. }
  1211. getId('routespeeds-routecount').innerHTML = 'Received <b>' + routesReceived.length + '</b> route' + (routesReceived.length == 1 ? '' : "s") + ' from the server';
  1212. sortRoutes();
  1213. }
  1214.  
  1215. getId('routespeeds-button-livemap').style.backgroundColor = '';
  1216. getId('routespeeds-button-reverse').style.backgroundColor = '';
  1217. switchRoute()
  1218. },
  1219. complete: function () {
  1220. console.timeEnd('WME Route Speeds: routing time');
  1221. routewait = 0;
  1222. }
  1223. });
  1224. }
  1225. //--------------------------------------------------------------------------------------------------------
  1226. function sortRoutes() {
  1227. routesShown = [...routesReceived];
  1228. if (!options.routingOrder) {
  1229. let sortByField = (options.routeType === 2) ? "length" : options.liveTraffic ? "crossTime" : "crossTimeWithoutRealTime";
  1230. routesShown.sort(function (a, b) {
  1231. let valField = "total_" + sortByField;
  1232. let val = function (r) {
  1233. if (r[valField] !== undefined) return r[valField];
  1234. let val = 0;
  1235. for (let i = 0; i < r.results.length; ++i) {
  1236. val += r.results[i][sortByField];
  1237. }
  1238. return r[valField] = val;
  1239. };
  1240. return val(a.response) - val(b.response);
  1241. });
  1242. }
  1243. if (routesShown.length > options.maxRoutes) {
  1244. routesShown = routesShown.slice(0, options.maxRoutes);
  1245. }
  1246. if (routeSelectedLast != -1) routeSelected = routeSelectedLast;
  1247. if (routeSelected >= routesShown.length) routeSelected = routesShown.length - 1;
  1248. createSummaries();
  1249. drawRoutes();
  1250. }
  1251. //--------------------------------------------------------------------------------------------------------
  1252. function createSummaries() {
  1253. var summaryDiv = getId('routespeeds-summaries');
  1254. summaryDiv.innerHTML = '';
  1255. let lengthUnit = options.useMiles ? "miles" : "km";
  1256. let speedUnit = options.useMiles ? "mph" : "km/h";
  1257. for (let i = 0; i < routesShown.length; i++) {
  1258. summaryDiv.innerHTML += '<div id=routespeeds-summary-' + i + ' class=routespeeds_summary_classA></div>';
  1259. }
  1260. for (let i = 0; i < routesShown.length; i++) {
  1261. let routeDiv = getId('routespeeds-summary-' + i);
  1262. routeDiv.onclick = function(){ toggleRoute(i) };
  1263. if (routeSelected == i) routeDiv.className = 'routespeeds_summary_classB';
  1264.  
  1265. let html = '<div class=routespeeds_header style="background: ' + getRouteColor(i) + '; color:#e0e0e0; "></div>' + '<div style="min-width:24px; display:inline-block; font-size:14px; color:#404040; text-align:right;"><b>' + (i+1) + '.</b></div>';
  1266.  
  1267. let lengthM = 0;
  1268. for (let s = 0; s < routesShown[i].response.results.length; s++) {
  1269. lengthM += routesShown[i].response.results[s].length;
  1270. }
  1271. let length = lengthM / 1000;
  1272. if (options.useMiles) length /= KM_PER_MILE;
  1273. let lengthText = length.toFixed(2);
  1274.  
  1275. let time = options.liveTraffic ? routesShown[i].response.totalRouteTime : routesShown[i].response.totalRouteTimeWithoutRealtime;
  1276. let timeText = getTimeText(time);
  1277.  
  1278. html += '<div style="min-width:57px; display:inline-block; font-size:14px; text-align:right;">' + lengthText + '</div>' + '<span style="color:#404040;"> ' + lengthUnit + '</span>';
  1279. html += '<div style="min-width:75px; display:inline-block; font-size:14px; text-align:right;"><b>' + timeText + '</b></div>';
  1280.  
  1281. let avgSpeed = getSpeed(lengthM, time);
  1282. html += '<div style="min-width:48px; display:inline-block; font-size:14px; text-align:right;" >' + avgSpeed.toFixed(1) + '</div><span style="color:#404040;"> ' + speedUnit + '</span>';
  1283.  
  1284. if (options.showRouteText) {
  1285. let maxWidth = options.useMiles ? 277 : 270;
  1286. let laneTypes = [];
  1287. if (routesShown[i].response.routeAttr.includes('Toll')) laneTypes.push('Toll');
  1288. laneTypes.push(...routesShown[i].response.laneTypes);
  1289. let separator = '';
  1290. if (routesShown[i].response.minPassengers) separator += " (" + routesShown[i].response.minPassengers + "+)";
  1291. if (laneTypes.length) separator += ': ';
  1292. html += '<div style="max-width:' + maxWidth + 'px; white-space:normal; line-height:normal; font-variant-numeric:normal;">' + laneTypes.join(', ') + separator + routesShown[i].response.routeName + '</div>';
  1293. }
  1294.  
  1295. routeDiv.innerHTML = html;
  1296. routeDiv.style.visibility = 'visible';
  1297. }
  1298.  
  1299. summaryDiv.style.visibility = 'visible';
  1300. }
  1301. //--------------------------------------------------------------------------------------------------------
  1302. function handleRouteRequestError(message) {
  1303. console.log("WME Route Speeds: route request error: " + message.replace("<br>", "\n"));
  1304.  
  1305. getId('routespeeds-button-livemap').style.backgroundColor = '';
  1306. getId('routespeeds-button-reverse').style.backgroundColor = '';
  1307.  
  1308. getId('routespeeds-summaries').style.visibility = 'hidden';
  1309. getId('routespeeds-summaries').innerHTML = '';
  1310.  
  1311. routesReceived = [];
  1312. sortRoutes();
  1313.  
  1314. getId('routespeeds-error').innerHTML = "<br>" + message;
  1315. getId('routespeeds-routecount').innerHTML = '';
  1316. }
  1317. //--------------------------------------------------------------------------------------------------------
  1318. function livemapRouteClick() {
  1319. routeSelected = 0;
  1320. routeSelectedLast = -1;
  1321.  
  1322. livemapRoute();
  1323. }
  1324. //--------------------------------------------------------------------------------------------------------
  1325. function get_coords_from_livemap_link(link) {
  1326. let lon1 = '';
  1327. let lat1 = '';
  1328. let lon2 = '';
  1329. let lat2 = '';
  1330.  
  1331. let opt = link.split('&');
  1332. for (let i = 0; i < opt.length; i++) {
  1333. let o = opt[i];
  1334.  
  1335. if (o.indexOf('from_lon=') === 0) lon1 = o.substring(9, 30);
  1336. if (o.indexOf('from_lat=') === 0) lat1 = ', ' + o.substring(9, 30);
  1337. if (o.indexOf('to_lon=') === 0) lon2 = o.substring(7, 30);
  1338. if (o.indexOf('to_lat=') === 0) lat2 = ', ' + o.substring(7, 30);
  1339. }
  1340.  
  1341. getId('sidepanel-routespeeds-a').value = lon1 + lat1;
  1342. getId('sidepanel-routespeeds-b').value = lon2 + lat2;
  1343. }
  1344. //--------------------------------------------------------------------------------------------------------
  1345. function livemapRoute() {
  1346.  
  1347. if (!options.enableScript) return;
  1348. if (routewait) return;
  1349.  
  1350. let stra = getId('sidepanel-routespeeds-a').value;
  1351. let strb = getId('sidepanel-routespeeds-b').value;
  1352.  
  1353. let pastedlink = false;
  1354.  
  1355. //sprawdzenie czy wklejono link z LiveMap, jeżeli tak to sparsowanie i przeformatowanie współrzędnych oraz przeniesienie widoku mapy na miejsce wklejonej trasy
  1356. //(checking if the link from LiveMap has been pasted, if yes, paring and reformatting the coordinates and moving the map view to the location of the pasted route)
  1357. if (stra.indexOf('livemap?') >= 0 || stra.indexOf('livemap/?') >= 0) {
  1358. get_coords_from_livemap_link(stra);
  1359. stra = getId('sidepanel-routespeeds-a').value;
  1360. strb = getId('sidepanel-routespeeds-b').value;
  1361. pastedlink = true;
  1362. }
  1363. else if (strb.indexOf('livemap?') >= 0 || strb.indexOf('livemap/?') >= 0) {
  1364. get_coords_from_livemap_link(strb);
  1365. stra = getId('sidepanel-routespeeds-a').value;
  1366. strb = getId('sidepanel-routespeeds-b').value;
  1367. pastedlink = true;
  1368. }
  1369.  
  1370. stra = getId('sidepanel-routespeeds-a').value;
  1371. strb = getId('sidepanel-routespeeds-b').value;
  1372. if (stra === "") return;
  1373. if (strb === "") return;
  1374.  
  1375. let p1 = stra.split(",");
  1376. let p2 = strb.split(",");
  1377.  
  1378. if (p1.length < 2) return;
  1379. if (p2.length < 2) return;
  1380.  
  1381. let x1 = p1[0].trim();
  1382. let y1 = p1[1].trim();
  1383. let x2 = p2[0].trim();
  1384. let y2 = p2[1].trim();
  1385.  
  1386. x1 = parseFloat(x1);
  1387. y1 = parseFloat(y1);
  1388. x2 = parseFloat(x2);
  1389. y2 = parseFloat(y2);
  1390.  
  1391. if (isNaN(x1)) return;
  1392. if (isNaN(y1)) return;
  1393. if (isNaN(x2)) return;
  1394. if (isNaN(y2)) return;
  1395.  
  1396. if (x1 < -180 || x1 > 180) x1 = 0;
  1397. if (x2 < -180 || x2 > 180) x2 = 0;
  1398. if (y1 < -90 || y1 > 90) y1 = 0;
  1399. if (y2 < -90 || y2 > 90) y2 = 0;
  1400.  
  1401. let objprog1 = getId('routespeeds-button-livemap');
  1402. objprog1.style.backgroundColor = '#FF8000';
  1403.  
  1404. createMarkers(x1, y1, x2, y2, true);
  1405.  
  1406. if (pastedlink) {
  1407. clickA();
  1408. }
  1409.  
  1410. requestRouteFromLiveMap(x1, y1, x2, y2);
  1411. }
  1412. //--------------------------------------------------------------------------------------------------------
  1413. function reverseRoute() {
  1414.  
  1415. if (!options.enableScript) return;
  1416. if (routewait) return;
  1417.  
  1418. let stra = getId('sidepanel-routespeeds-b').value;
  1419. let strb = getId('sidepanel-routespeeds-a').value;
  1420. if (stra === "") return;
  1421. if (strb === "") return;
  1422.  
  1423. getId('sidepanel-routespeeds-a').value = stra;
  1424. getId('sidepanel-routespeeds-b').value = strb;
  1425.  
  1426. let p1 = stra.split(",");
  1427. let p2 = strb.split(",");
  1428.  
  1429. if (p1.length < 2) return;
  1430. if (p2.length < 2) return;
  1431.  
  1432. let x1 = p1[0].trim();
  1433. let y1 = p1[1].trim();
  1434. let x2 = p2[0].trim();
  1435. let y2 = p2[1].trim();
  1436.  
  1437. x1 = parseFloat(x1);
  1438. y1 = parseFloat(y1);
  1439. x2 = parseFloat(x2);
  1440. y2 = parseFloat(y2);
  1441.  
  1442. if (isNaN(x1)) return;
  1443. if (isNaN(y1)) return;
  1444. if (isNaN(x2)) return;
  1445. if (isNaN(y2)) return;
  1446.  
  1447. if (x1 < -180 || x1 > 180) x1 = 0;
  1448. if (x2 < -180 || x2 > 180) x2 = 0;
  1449. if (y1 < -90 || y1 > 90) y1 = 0;
  1450. if (y2 < -90 || y2 > 90) y2 = 0;
  1451.  
  1452. let objprog2 = getId('routespeeds-button-reverse');
  1453. objprog2.style.backgroundColor = '#FF8000';
  1454.  
  1455. createMarkers(x1, y1, x2, y2, true);
  1456.  
  1457. requestRouteFromLiveMap(x1, y1, x2, y2);
  1458. }
  1459. //--------------------------------------------------------------------------------------------------------
  1460. function resetOptions() {
  1461.  
  1462. getId('routespeeds-getalternatives').checked = options.getAlternatives = true;
  1463. getId('routespeeds-maxroutes').value = options.maxRoutes = 3;
  1464.  
  1465. getId('routespeeds-livetraffic').checked = options.liveTraffic = false;
  1466.  
  1467. getId('routespeeds-routetype').value = options.routeType = 1;
  1468.  
  1469. getId('routespeeds-avoidtolls').checked = options.avoidTolls = false;
  1470. getId('routespeeds-avoidfreeways').checked = options.avoidFreeways = false;
  1471. getId('routespeeds-avoidunpaved').checked = options.avoidUnpaved = true;
  1472. getId('routespeeds-avoidlongunpaved').checked = options.avoidLongUnpaved = false;
  1473. getId('routespeeds-allowuturns').checked = options.allowUTurns = true;
  1474. getId('routespeeds-routingorder').checked = options.routingOrder = true;
  1475. getId('routespeeds-userbs').checked = options.useRBS = false;
  1476. getId('routespeeds-avoiddifficult').checked = options.avoidDifficult = false;
  1477. getId('routespeeds-avoidferries').checked = options.avoidFerries = false;
  1478. getId('routespeeds-vehicletype').value = options.vehicleType = 'PRIVATE';
  1479. }
  1480. //--------------------------------------------------------------------------------------------------------
  1481. function resetOptionsToLivemapRouteClick() {
  1482. if (routewait) return;
  1483.  
  1484. resetOptions();
  1485.  
  1486. $(`.routespeeds-pass-checkbox`).prop( "checked", false );;
  1487. options.passes = [];
  1488.  
  1489. livemapRoute();
  1490. }
  1491. //--------------------------------------------------------------------------------------------------------
  1492. function hourChange() {
  1493.  
  1494. livemapRoute();
  1495. }
  1496. //--------------------------------------------------------------------------------------------------------
  1497. function dayChange() {
  1498.  
  1499. livemapRoute();
  1500. }
  1501. //--------------------------------------------------------------------------------------------------------
  1502. function clickA() { gotoMarker(markerA); }
  1503. function clickB() { gotoMarker(markerB); }
  1504. //--------------------------------------------------------------------------------------------------------
  1505. function gotoMarker(marker) {
  1506.  
  1507. if (!options.enableScript || marker === undefined || !marker.created) return;
  1508.  
  1509. let pt = marker.lonlat;
  1510. let zoom = W.map.getZoom();
  1511.  
  1512. W.map.getOLMap().setCenter([pt.lon, pt.lat], zoom);
  1513. }
  1514. //--------------------------------------------------------------------------------------------------------
  1515. function clickEnableScript() {
  1516. var WM = W.map;
  1517.  
  1518. options.enableScript = (getId('routespeeds-enablescript').checked === true);
  1519.  
  1520. if (!options.enableScript) {
  1521. getId('sidepanel-routespeeds').style.color = "#A0A0A0";
  1522.  
  1523. getId('routespeeds-summaries').style.visibility = 'hidden';
  1524.  
  1525. let rlayers = WM.getLayersBy("uniqueName", "__DrawRouteSpeedsLines");
  1526. let routeLayer = rlayers[0];
  1527. if (routeLayer !== undefined) routeLayer.removeAllFeatures();
  1528.  
  1529. showMarkers(false);
  1530. reorderLayers(0);
  1531. }
  1532. else {
  1533. getId('sidepanel-routespeeds').style.color = "";
  1534.  
  1535. if (showMarkers(true)) drawRoutes();
  1536. reorderLayers(1);
  1537. }
  1538. }
  1539. //--------------------------------------------------------------------------------------------------------
  1540. function clickShowLabels() {
  1541. options.showLabels = (getId('routespeeds-showLabels').checked === true);
  1542. drawRoutes();
  1543. }
  1544. //--------------------------------------------------------------------------------------------------------
  1545. function clickShowSpeeds() {
  1546. options.showSpeeds = (getId('routespeeds-showSpeeds').checked === true);
  1547. drawRoutes();
  1548. }
  1549. //--------------------------------------------------------------------------------------------------------
  1550. function clickUseMiles() {
  1551. options.useMiles = (getId('routespeeds-usemiles').checked === true);
  1552. createSummaries();
  1553. drawRoutes();
  1554. }
  1555. //--------------------------------------------------------------------------------------------------------
  1556. function clickShowRouteText() {
  1557. options.showRouteText = (getId('routespeeds-routetext').checked === true);
  1558. createSummaries();
  1559. }
  1560. //--------------------------------------------------------------------------------------------------------
  1561. function clickGetAlternatives() {
  1562. routeSelected = 0;
  1563. routeSelectedLast = -1;
  1564.  
  1565. options.getAlternatives = (getId('routespeeds-getalternatives').checked === true);
  1566. if (options.getAlternatives && routesReceived.length < options.maxRoutes) {
  1567. livemapRoute();
  1568. } else {
  1569. sortRoutes();
  1570. }
  1571. }
  1572. //--------------------------------------------------------------------------------------------------------
  1573. function clickMaxRoutes() {
  1574. options.getAlternatives = (getId('routespeeds-getalternatives').checked === true);
  1575.  
  1576. options.maxRoutes = parseInt(getId('routespeeds-maxroutes').value);
  1577. if (options.getAlternatives && routesReceived.length < options.maxRoutes) {
  1578. livemapRoute();
  1579. } else {
  1580. sortRoutes();
  1581. }
  1582. }
  1583. //--------------------------------------------------------------------------------------------------------
  1584. function clickLiveTraffic() {
  1585. options.liveTraffic = (getId('routespeeds-livetraffic').checked === true);
  1586. sortRoutes();
  1587. }
  1588. //--------------------------------------------------------------------------------------------------------
  1589. function clickAvoidTolls() {
  1590. options.avoidTolls = (getId('routespeeds-avoidtolls').checked === true);
  1591. livemapRoute();
  1592. }
  1593. //--------------------------------------------------------------------------------------------------------
  1594. function clickAvoidFreeways() {
  1595. options.avoidFreeways = (getId('routespeeds-avoidfreeways').checked === true);
  1596. livemapRoute();
  1597. }
  1598. //--------------------------------------------------------------------------------------------------------
  1599. function clickAvoidUnpaved() {
  1600. options.avoidUnpaved = (getId('routespeeds-avoidunpaved').checked === true);
  1601.  
  1602. options.avoidLongUnpaved = false;
  1603. getId('routespeeds-avoidlongunpaved').checked = false;
  1604.  
  1605. livemapRoute();
  1606. }
  1607. //--------------------------------------------------------------------------------------------------------
  1608. function clickAvoidLongUnpaved() {
  1609. options.avoidLongUnpaved = (getId('routespeeds-avoidlongunpaved').checked === true);
  1610.  
  1611. options.avoidUnpaved = false;
  1612. getId('routespeeds-avoidunpaved').checked = false;
  1613.  
  1614. livemapRoute();
  1615. }
  1616. //--------------------------------------------------------------------------------------------------------
  1617. function clickRouteType() {
  1618. options.routeType = parseInt(getId('routespeeds-routetype').value);
  1619. livemapRoute();
  1620. }
  1621. //--------------------------------------------------------------------------------------------------------
  1622. function clickAllowUTurns() {
  1623. options.allowUTurns = (getId('routespeeds-allowuturns').checked === true);
  1624. livemapRoute();
  1625. }
  1626. //--------------------------------------------------------------------------------------------------------
  1627. function clickRoutingOrder() {
  1628. options.routingOrder = (getId('routespeeds-routingorder').checked === true);
  1629. sortRoutes();
  1630. }
  1631. //--------------------------------------------------------------------------------------------------------
  1632. function clickUseRBS() {
  1633. options.useRBS = (getId('routespeeds-userbs').checked === true);
  1634. livemapRoute();
  1635. }
  1636. //--------------------------------------------------------------------------------------------------------
  1637. function clickAvoidDifficult() {
  1638. options.avoidDifficult = (getId('routespeeds-avoiddifficult').checked === true);
  1639. livemapRoute();
  1640. }
  1641. //--------------------------------------------------------------------------------------------------------
  1642. function clickAvoidFerries() {
  1643. options.avoidFerries = (getId('routespeeds-avoidferries').checked === true);
  1644. livemapRoute();
  1645. }
  1646. //--------------------------------------------------------------------------------------------------------
  1647. function clickVehicleType() {
  1648. options.vehicleType = (getId('routespeeds-vehicletype').value);
  1649. livemapRoute();
  1650. }
  1651. //--------------------------------------------------------------------------------------------------------
  1652. function clickPassOption() {
  1653. let passKey = $(this).data('pass-key');
  1654. if (this.checked) {
  1655. options.passes.push(passKey);
  1656. } else {
  1657. options.passes = options.passes.filter(key => key !== passKey)
  1658. }
  1659. updatePassesLabel();
  1660. livemapRoute();
  1661. }
  1662. //--------------------------------------------------------------------------------------------------------
  1663. function toggleRoute(routeNo) {
  1664. if (routeSelected === routeNo) routeNo = -1;
  1665. routeSelectedLast = routeSelected = routeNo;
  1666. switchRoute();
  1667. }
  1668. //--------------------------------------------------------------------------------------------------------
  1669. function switchRoute() {
  1670. for (let i = 0; i < routesShown.length; i++) {
  1671. let summary = getId('routespeeds-summary-' + i);
  1672. summary.className = (routeSelected == i) ? 'routespeeds_summary_classB' : 'routespeeds_summary_classA';
  1673. }
  1674.  
  1675. let rlayers = W.map.getLayersBy("uniqueName", "__DrawRouteSpeedsLines");
  1676. let routeLayer = rlayers[0];
  1677. if (routeLayer === undefined) return;
  1678.  
  1679. for (let uniqueName of SCRIPT_LAYERS_TO_COVER) {
  1680. let layer = W.map.getLayersBy("uniqueName", uniqueName)[0];
  1681. if (layer === undefined) continue;
  1682. baseZIndex = Math.max(baseZIndex, layer.getZIndex());
  1683. }
  1684. if (routeLayer.getZIndex() < baseZIndex) {
  1685. routeLayer.setZIndex(baseZIndex + 1);
  1686. } else {
  1687. baseZIndex = routeLayer.getZIndex();
  1688. }
  1689. reorderLayers(1);
  1690.  
  1691. drawRoutes();
  1692. }
  1693. //--------------------------------------------------------------------------------------------------------
  1694. function reorderLayers(mode) {
  1695. if (baseZIndex == 0) return;
  1696. for (let i = 0; i < WME_LAYERS_TO_MOVE.length; i++) {
  1697. if (layersMoved[i] === undefined) {
  1698. let layer = W.map.getLayersBy("name", WME_LAYERS_TO_MOVE[i])[0];
  1699. if (layer === undefined) continue;
  1700. layersMoved[i] = layer;
  1701. originalZIndexes[i] = layer.getZIndex();
  1702. }
  1703. if (mode) {
  1704. layersMoved[i].setZIndex(baseZIndex - WME_LAYERS_TO_MOVE.length + i);
  1705. } else {
  1706. layersMoved[i].setZIndex(originalZIndexes[i]);
  1707. }
  1708. layersMoved[i].redraw();
  1709. }
  1710. }
  1711. //--------------------------------------------------------------------------------------------------------
  1712. function drawRoutes() {
  1713.  
  1714. var routeLayer = W.map.getLayersBy("uniqueName", "__DrawRouteSpeedsLines")[0];
  1715. if (routeLayer !== undefined) routeLayer.removeAllFeatures();
  1716.  
  1717. for (let i = routesShown.length - 1; i >= 0; i--) {
  1718. if (i == routeSelected) continue;
  1719. createRouteFeatures(i, routesShown[i].coords, routesShown[i].response.results)
  1720. }
  1721. if (routeSelected != -1 && routesShown.length) {
  1722. createRouteFeatures(routeSelected, routesShown[routeSelected].coords, routesShown[routeSelected].response.results)
  1723. }
  1724. }
  1725. //--------------------------------------------------------------------------------------------------------
  1726. function enterAB(ev) {
  1727. if (ev.keyCode === 13) {
  1728. livemapRoute();
  1729. }
  1730. }
  1731. //--------------------------------------------------------------------------------------------------------
  1732. function getCheckboxHtml(idSuffix, text, title, divCss = {}, labelCss = {}) {
  1733. let id = 'routespeeds-' + idSuffix;
  1734. return $('<div>', { class: 'controls-container' }).append(
  1735. $('<input>', { id: id, type: 'checkbox' }),
  1736. $('<label>', { for: id, title: title }).text(text).css(labelCss)
  1737. ).css(divCss)[0].outerHTML;
  1738. }
  1739. //--------------------------------------------------------------------------------------------------------
  1740. async function initialiseWMERouteSpeeds() {
  1741. var line_div_break = '<br>';
  1742. line_div_break += '</div>';
  1743. line_div_break += '<div style="margin-left:55px">';
  1744.  
  1745. if (W.loginManager !== null && W.loginManager.user) {
  1746. var user = W.loginManager.user;
  1747. //console.log(user);
  1748.  
  1749. //wlodek76: I prefer more condensed lines for avoid options, so I've added a personal switch here
  1750. if (user !== null) {
  1751. if (user.userName === "wlodek76" && user.id === 203457007) {
  1752. line_div_break = '';
  1753. }
  1754. }
  1755. }
  1756.  
  1757. epsg900913 = new OpenLayers.Projection("EPSG:900913");
  1758. epsg4326 = new OpenLayers.Projection("EPSG:4326");
  1759.  
  1760. var addon = document.createElement('section');
  1761. addon.id = "routespeeds-addon";
  1762. addon.innerHTML = '' +
  1763. '<div id="sidepanel-routespeeds" style="margin: 0px 8px; width: auto;">' +
  1764. '<div style="margin-bottom:4px; padding:0px;"><a href="https://greatest.deepsurf.us/en/scripts/369630-wme-route-speeds-mapomatic-fork" target="_blank">' +
  1765. '<span style="font-weight:bold; text-decoration:underline">WME Route Speeds</span></a><span style="margin-left:6px; color:#888; font-size:11px;">v' + wmech_version + '</span>' +
  1766. '</div>' +
  1767. '<style>\n' +
  1768. '#sidepanel-routespeeds select { margin-left:20px; font-size:12px; height:22px; border:1px solid; border-color:rgb(169, 169, 169); border-radius:4px; border: 1px solid; border-color: rgb(169, 169, 169); -webkit-border-radius:4px; -moz-border-radius:4px; }\n' +
  1769. '#sidepanel-routespeeds select, #sidepanel-routespeeds input { margin-top:2px; margin-bottom:2px; width:initial; }\n' +
  1770. '#sidepanel-routespeeds input[type="checkbox"] { margin-bottom:0px; }\n' +
  1771. '#sidepanel-routespeeds label ~ label, #sidepanel-routespeeds span label { margin-left:20px; }\n' +
  1772. '#sidepanel-routespeeds .controls-container { padding:0px; }\n' +
  1773. '#sidepanel-routespeeds label { font-weight:normal; }\n' +
  1774. '</style>' +
  1775. '<div style="float:left; display:inline-block;">' +
  1776. '<a id="routespeeds-button-A" onclick="return false;" style="cursor:pointer; width:20px; display:inline-block; vertical-align:middle;" title="Center map on A marker">A:</a>' +
  1777. '<input id="sidepanel-routespeeds-a" class="form-control" style="width:165px; padding:6px; margin:0px; display:inline; height:24px" type="text" name=""/>' +
  1778. '<br><div style="height: 4px;"></div>' +
  1779. '<a id="routespeeds-button-B" onclick="return false;" style="cursor:pointer; width:20px; display:inline-block; vertical-align:middle;" title="Center map on B marker">B:</a>' +
  1780. '<input id="sidepanel-routespeeds-b" class="form-control" style="width:165px; padding:6px; margin:0px; display:inline; height:24px" type="text" name=""/>' +
  1781. '</div>' +
  1782. '<div style="float:right; padding-right:20px; padding-top:6%; ">' +
  1783. '<button id=routespeeds-button-reverse class="waze-btn waze-btn-blue waze-btn-smaller" style="padding-left:15px; padding-right:15px;" title="Calculate reverse route" >A &#8596; B</button></div>' +
  1784. '<div style="clear:both; "></div>' +
  1785.  
  1786. '<div style="margin-top:8px;">' +
  1787. '<select id=routespeeds-hour>' +
  1788. '<option value="now">Now</option>' +
  1789. '<option value="0" >00:00</option>' +
  1790. '<option value="30" >00:30</option>' +
  1791. '<option value="60" >01:00</option>' +
  1792. '<option value="90" >01:30</option>' +
  1793. '<option value="120">02:00</option>' +
  1794. '<option value="150">02:30</option>' +
  1795. '<option value="180">03:00</option>' +
  1796. '<option value="210">03:30</option>' +
  1797. '<option value="240">04:00</option>' +
  1798. '<option value="270">04:30</option>' +
  1799. '<option value="300">05:00</option>' +
  1800. '<option value="330">05:30</option>' +
  1801. '<option value="360">06:00</option>' +
  1802. '<option value="390">06:30</option>' +
  1803. '<option value="420">07:00</option>' +
  1804. '<option value="450">07:30</option>' +
  1805. '<option value="480">08:00</option>' +
  1806. '<option value="510">08:30</option>' +
  1807. '<option value="540">09:00</option>' +
  1808. '<option value="570">09:30</option>' +
  1809. '<option value="600">10:00</option>' +
  1810. '<option value="630">10:30</option>' +
  1811. '<option value="660">11:00</option>' +
  1812. '<option value="690">11:30</option>' +
  1813. '<option value="720">12:00</option>' +
  1814. '<option value="750">12:30</option>' +
  1815. '<option value="780">13:00</option>' +
  1816. '<option value="810">13:30</option>' +
  1817. '<option value="840">14:00</option>' +
  1818. '<option value="870">14:30</option>' +
  1819. '<option value="900">15:00</option>' +
  1820. '<option value="930">15:30</option>' +
  1821. '<option value="960">16:00</option>' +
  1822. '<option value="990">16:30</option>' +
  1823. '<option value="1020">17:00</option>' +
  1824. '<option value="1050">17:30</option>' +
  1825. '<option value="1080">18:00</option>' +
  1826. '<option value="1110">18:30</option>' +
  1827. '<option value="1140">19:00</option>' +
  1828. '<option value="1170">19:30</option>' +
  1829. '<option value="1200">20:00</option>' +
  1830. '<option value="1230">20:30</option>' +
  1831. '<option value="1260">21:00</option>' +
  1832. '<option value="1290">21:30</option>' +
  1833. '<option value="1320">22:00</option>' +
  1834. '<option value="1350">22:30</option>' +
  1835. '<option value="1380">23:00</option>' +
  1836. '<option value="1410">23:30</option>' +
  1837. '</select>' +
  1838. '<select id=routespeeds-day style="margin-left:5px;" >' +
  1839. '<option value="today">Today</option>' +
  1840. '<option value="1">Monday</option>' +
  1841. '<option value="2">Tuesday</option>' +
  1842. '<option value="3">Wednesday</option>' +
  1843. '<option value="4">Thursday</option>' +
  1844. '<option value="5">Friday</option>' +
  1845. '<option value="6">Saturday</option>' +
  1846. '<option value="0">Sunday</option>' +
  1847. '</select>' +
  1848. '</div>' +
  1849.  
  1850. '<div style="padding-top:8px; padding-bottom:6px;">' +
  1851. '<button id=routespeeds-button-livemap class="waze-btn waze-btn-blue waze-btn-smaller" style="width:100%;">Calculate Route</button>' +
  1852. '</div>' +
  1853. '<b><div id=routespeeds-error style="color:#FF0000"></div></b>' +
  1854. '<div id=routespeeds-routecount></div>' +
  1855.  
  1856. '<div id=routespeeds-summaries style="font-size:11px; font-variant-numeric:tabular-nums;"></div>' +
  1857.  
  1858. '<div style="margin-bottom:4px;">' +
  1859. '<b>Options:</b>' +
  1860. '<a id="routespeeds-reset-options-to-livemap-route" onclick="return false;" style="cursor:pointer; float:right; margin-right:20px;" title="Reset routing options to the Livemap Route equivalents">Reset to Livemap Route</a>' +
  1861. '</div>' +
  1862.  
  1863. getCheckboxHtml('enablescript', 'Enable script') +
  1864. getCheckboxHtml('showLabels', 'Show segment labels') +
  1865. getCheckboxHtml('livetraffic', 'Use real-time traffic', 'Note: this only seems to affect routes within the last 30-60 minutes, up to Now') +
  1866. getCheckboxHtml('showSpeeds', 'Show speed on labels') +
  1867. getCheckboxHtml('usemiles', 'Use miles and mph') +
  1868. getCheckboxHtml('routetext', 'Show route descriptions') +
  1869.  
  1870. '<div>' +
  1871. getCheckboxHtml('getalternatives', 'Alternative routes: show', '', { display: 'inline-block' }) +
  1872. '<select id=routespeeds-maxroutes style="margin-left:-4px; display:inline-block;" >' +
  1873. '<option id=routespeeds-maxroutes value="1">1</option>' +
  1874. '<option id=routespeeds-maxroutes value="2">2</option>' +
  1875. '<option id=routespeeds-maxroutes value="3">3</option>' +
  1876. '<option id=routespeeds-maxroutes value="4">4</option>' +
  1877. '<option id=routespeeds-maxroutes value="5">5</option>' +
  1878. '<option id=routespeeds-maxroutes value="6">6</option>' +
  1879. '<option id=routespeeds-maxroutes value="8">8</option>' +
  1880. '<option id=routespeeds-maxroutes value="10">10</option>' +
  1881. '<option id=routespeeds-maxroutes value="12">12</option>' +
  1882. '<option id=routespeeds-maxroutes value="15">15</option>' +
  1883. '<option id=routespeeds-maxroutes value="40">all</option>' +
  1884.  
  1885. '</select>' +
  1886. '</div>' +
  1887.  
  1888. getCheckboxHtml('routingorder', 'Use Routing Order', 'Sorts routes in the same order they would appear in the app or livemap') +
  1889.  
  1890. getCheckboxHtml('userbs', 'Use Routing Beta Server (RBS)', '', { display: window.location.hostname.includes('beta') ? 'inline' : 'none' }) +
  1891.  
  1892. '<div>' +
  1893. '<label class="" style="display:inline-block;">' +
  1894. 'Route type:<select id=routespeeds-routetype style="margin-left:10px;" >' +
  1895. '<option value="1">Fastest</option>' +
  1896. '<option value="3">Fastest (no history)</option>' +
  1897. '</select>' +
  1898. '<br>' +
  1899. 'Vehicle type:<select id=routespeeds-vehicletype style="margin-left:10px;" >' +
  1900. '<option id=routespeeds-vehicletype value="PRIVATE">Private</option>' +
  1901. '<option id=routespeeds-vehicletype value="TAXI">Taxi</option>' +
  1902. '<option id=routespeeds-vehicletype value="MOTORCYCLE">Motorcycle</option>' +
  1903. '</select>' +
  1904. '</div>' +
  1905.  
  1906. '<table><tbody><tr><td style="vertical-align:top; padding-right:4px;"><b>Avoid:</b></td><td>' +
  1907. getCheckboxHtml('avoidtolls', 'Tolls') +
  1908. getCheckboxHtml('avoidfreeways', 'Freeways') +
  1909. getCheckboxHtml('avoiddifficult', 'Difficult turns') +
  1910. getCheckboxHtml('avoidferries', 'Ferries') +
  1911. getCheckboxHtml('avoidunpaved', 'Unpaved') +
  1912. '<div id="routespeeds-avoidunpaved-span" style="display:inline;">' +
  1913. getCheckboxHtml('avoidlongunpaved', 'Long unpaved roads', '', { marginLeft: '10px' }) +
  1914. '</div>' +
  1915. '</td></tr></tbody></table>' +
  1916.  
  1917. '<table style="margin-top:3px;"><tbody><tr><td style="vertical-align:top; padding-right:4px;"><b>Allow:</b></td><td>' +
  1918. getCheckboxHtml('allowuturns', 'U-Turns') +
  1919. '</td></tr></tbody></table>' +
  1920. '<div id="routespeeds-passes-container"></div>' +
  1921. '<style>' +
  1922. '.routespeedsmarkerA { display:block; width:27px; height:36px; margin-left:-13px; margin-top:-34px; }' +
  1923. '.routespeedsmarkerB { display:block; width:27px; height:36px; margin-left:-13px; margin-top:-34px; }' +
  1924. //+ '.routespeedsmarkerA { background:url("http://341444cc-a-62cb3a1a-s-sites.googlegroups.com/site/wazeaddons/routespeeds_marker_a.png"); }'
  1925. //+ '.routespeedsmarkerB { background:url("http://341444cc-a-62cb3a1a-s-sites.googlegroups.com/site/wazeaddons/routespeeds_marker_b.png"); }'
  1926. '.routespeedsmarkerA { background-image:url(data:image/png;base64,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); }' +
  1927. '.routespeedsmarkerB { background-image:url(data:image/png;base64,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); }' +
  1928. '.routespeedsmarkerA:hover { cursor:move }' +
  1929. '.routespeedsmarkerB:hover { cursor:move }' +
  1930. '.routespeeds_summary_classA { visibility:hidden; display:inline-block; color:#000000; margin:2px 0px 2px 0px; padding:2px 6px 2px 4px; border:1px solid #c0c0c0; background:#F8F8F8; border-radius:4px; vertical-align:middle; white-space:nowrap; }' +
  1931. '.routespeeds_summary_classB { visibility:hidden; display:inline-block; color:#000000; margin:2px 0px 2px 0px; padding:2px 6px 2px 4px; border:1px solid #c0c0c0; background:#d0fffe; border-radius:4px; vertical-align:middle; white-space:nowrap; }' +
  1932. '.routespeeds_summary_classA:hover { cursor:pointer; border:1px solid #808080; xbackground:#a0fffd; }' +
  1933. '.routespeeds_summary_classB:hover { cursor:pointer; border:1px solid #808080; xbackground:#a0fffd; }' +
  1934. '.routespeeds_header { display:inline-block; width:14px; height:14px; text-align:center; border-radius:2px; margin-right:2px; position:relative; top:2px; }' +
  1935. '</style>' +
  1936. '</div>';
  1937.  
  1938. /*var userTabs = getId('user-info');
  1939. var navTabs = getElementsByClassName('nav-tabs', userTabs)[0];
  1940. var tabContent = getElementsByClassName('tab-content', userTabs)[0];
  1941.  
  1942. newtab = document.createElement('li');
  1943. newtab.innerHTML = '<a id=sidepanel-routespeeds href="#sidepanel-routespeeds" data-toggle="tab" style="" >Route Speeds</a>';
  1944. navTabs.appendChild(newtab);
  1945.  
  1946. addon.id = "sidepanel-routespeeds";
  1947. addon.className = "tab-pane";
  1948. tabContent.appendChild(addon);*/
  1949.  
  1950. $('head').append([
  1951. '<style>',
  1952. 'label[for^="routespeeds-"] { margin-right: 10px;padding-left: 19px; }',
  1953. '.hidden { display:none; }',
  1954. '</style>'
  1955. ].join('\n'));
  1956.  
  1957. WazeWrap.Interface.Tab('Route Speeds', addon.innerHTML, init, '<span id="routespeeds-tab-label">Route Speeds</span>');
  1958.  
  1959. window.addEventListener("beforeunload", saveRouteSpeedsOptions, true);
  1960. }
  1961.  
  1962. let _lastTopCountryId;
  1963. function buildPassesDiv() {
  1964. $('#routespeeds-passes-container').empty();
  1965. let passesObj = W.model.getTopCountry().attributes.restrictionSubscriptions;
  1966. if (passesObj) {
  1967. countryPassList = Object.keys(passesObj).map(key => { return { key: key, name: passesObj[key] } }).sort((a, b) => {
  1968. if (a.name > b.name) {
  1969. return 1;
  1970. } else if (a.name < b.name) {
  1971. return -1;
  1972. }
  1973. return 0;
  1974. });
  1975. } else {
  1976. countryPassList = [];
  1977. }
  1978.  
  1979. if (countryPassList.length) {
  1980. $('#routespeeds-passes-container').append(
  1981. '<fieldset style="border:1px solid silver;padding:8px;border-radius:4px;-webkit-padding-before: 0;">' +
  1982. ' <legend id="routespeeds-passes-legend" style="margin-bottom:0px;border-bottom-style:none;width:auto;">' +
  1983. ' <i class="fa fa-fw fa-chevron-down" style="cursor: pointer;font-size: 12px;margin-right: 4px"></i>' +
  1984. ' <span id="routespeeds-passes-label" style="font-size:14px;font-weight:600; cursor: pointer">Passes & Permits</span>' +
  1985. ' </legend>' +
  1986. ' <div id="routespeeds-passes-internal-container" style="padding-top:0px;">' +
  1987. countryPassList.map((pass, i) => {
  1988. //let id = 'routespeeds-pass-' + pass.key;
  1989. return ' <div class="controls-container" style="padding-top:2px;display:block;">' +
  1990. ' <input id="routespeeds-pass-' + i + '" type="checkbox" class="routespeeds-pass-checkbox" data-pass-key = "' + pass.key + '">' +
  1991. ' <label for="routespeeds-pass-' + i + '" style="white-space:pre-line">' + pass.name + '</label>' +
  1992. ' </div>';
  1993. }).join(' ') +
  1994. ' </div>' +
  1995. '</fieldset>'
  1996. );
  1997.  
  1998. $('.routespeeds-pass-checkbox').click(clickPassOption);
  1999.  
  2000. $('#routespeeds-passes-legend').click(function () {
  2001. let $this = $(this);
  2002. let $chevron = $($this.children()[0]);
  2003. $chevron
  2004. .toggleClass('fa fa-fw fa-chevron-down')
  2005. .toggleClass('fa fa-fw fa-chevron-right');
  2006. let collapse = $chevron.hasClass('fa-chevron-right');
  2007. let checkboxDivs = $('input.routespeeds-pass-checkbox:not(:checked)').parent();
  2008. if (collapse) {
  2009. checkboxDivs.css('display', 'none');
  2010. } else {
  2011. checkboxDivs.css('display', 'block');
  2012. }
  2013. // $($this.children()[0])
  2014. // .toggleClass('fa fa-fw fa-chevron-down')
  2015. // .toggleClass('fa fa-fw fa-chevron-right');
  2016. // $($this.siblings()[0]).toggleClass('collapse');
  2017. })
  2018.  
  2019. $('.routespeeds-pass-checkbox').each((i, elem) => {
  2020. const $elem = $(elem);
  2021. const passKey = $elem.data('pass-key');
  2022. $elem.prop('checked', options.passes.includes(passKey));
  2023. });
  2024. updatePassesLabel();
  2025. }
  2026. }
  2027.  
  2028.  
  2029. function onModelMergeEnd() {
  2030. // Detect when the "top" country changes and update the list of passes.
  2031. try {
  2032. const topCountry = W.model.getTopCountry();
  2033. if (topCountry && topCountry.attributes.id !== _lastTopCountryId) {
  2034. _lastTopCountryId = topCountry.attributes.id;
  2035. buildPassesDiv();
  2036. }
  2037. } catch (ex) {
  2038. console.error('WME Route Speeds error: ', ex);
  2039. }
  2040. }
  2041.  
  2042. function init() {
  2043. resetOptions();
  2044. loadRouteSpeedsOptions();
  2045.  
  2046. if (!options.enableScript) getId('sidepanel-routespeeds').style.color = "#A0A0A0";
  2047. else getId('sidepanel-routespeeds').style.color = "";
  2048.  
  2049. getId('routespeeds-maxroutes').value = options.maxRoutes;
  2050. getId('routespeeds-routetype').value = options.routeType;
  2051. getId('routespeeds-vehicletype').value = options.vehicleType;
  2052. getId('routespeeds-userbs').onclick = clickUseRBS;
  2053.  
  2054. getId('routespeeds-enablescript').onclick = clickEnableScript;
  2055. getId('routespeeds-showLabels').onclick = clickShowLabels;
  2056. getId('routespeeds-showSpeeds').onclick = clickShowSpeeds;
  2057. getId('routespeeds-usemiles').onclick = clickUseMiles;
  2058. getId('routespeeds-routetext').onclick = clickShowRouteText;
  2059. getId('routespeeds-getalternatives').onclick = clickGetAlternatives;
  2060. getId('routespeeds-maxroutes').onchange = clickMaxRoutes;
  2061. getId('routespeeds-livetraffic').onclick = clickLiveTraffic;
  2062. getId('routespeeds-avoidtolls').onclick = clickAvoidTolls;
  2063. getId('routespeeds-avoidfreeways').onclick = clickAvoidFreeways;
  2064. getId('routespeeds-avoidunpaved').onclick = clickAvoidUnpaved;
  2065. getId('routespeeds-avoidlongunpaved').onclick = clickAvoidLongUnpaved;
  2066. getId('routespeeds-routetype').onchange = clickRouteType;
  2067. getId('routespeeds-allowuturns').onclick = clickAllowUTurns;
  2068. getId('routespeeds-routingorder').onclick = clickRoutingOrder;
  2069. getId('routespeeds-avoiddifficult').onclick = clickAvoidDifficult;
  2070. getId('routespeeds-avoidferries').onclick = clickAvoidFerries;
  2071. getId('routespeeds-vehicletype').onchange = clickVehicleType;
  2072.  
  2073. getId('sidepanel-routespeeds-a').onkeydown = enterAB;
  2074. getId('sidepanel-routespeeds-b').onkeydown = enterAB;
  2075.  
  2076. getId('routespeeds-button-livemap').onclick = livemapRouteClick;
  2077. getId('routespeeds-button-reverse').onclick = reverseRoute;
  2078. getId('routespeeds-reset-options-to-livemap-route').onclick = resetOptionsToLivemapRouteClick;
  2079.  
  2080. getId('routespeeds-hour').onchange = hourChange;
  2081. getId('routespeeds-day').onchange = dayChange;
  2082.  
  2083. getId('routespeeds-button-A').onclick = clickA;
  2084. getId('routespeeds-button-B').onclick = clickB;
  2085.  
  2086. const topCountry = W.model.getTopCountry();
  2087. if (topCountry) {
  2088. _lastTopCountryId = topCountry.attributes.id;
  2089. buildPassesDiv();
  2090. }
  2091.  
  2092. //WazeWrap.Events.register('zoomend', null, drawRoutes);
  2093. W.model.events.register('mergeend', null, onModelMergeEnd);
  2094.  
  2095. window.setInterval(loopWMERouteSpeeds, 500);
  2096. window.setInterval(panningWMERouteSpeeds, 100);
  2097. }
  2098. //--------------------------------------------------------------------------------------------------------------
  2099. bootstrap();
  2100. })();