Greasy Fork is available in English.

WME Route Speeds (MapOMatic fork)

Shows segment speeds in a route.

Versão de: 07/09/2024. Veja: a última versão.

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