WME Color Highlights

Adds colours to road segments to show their status

当前为 2017-07-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WME Color Highlights
  3. // @namespace http://userscripts.org/users/419370
  4. // @description Adds colours to road segments to show their status
  5. // @match https://*.waze.com/*editor/*
  6. // @exclude https://*.waze.com/*user/editor/*
  7. // @version 2.23
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function()
  12. {
  13.  
  14. // global variables
  15. var wmech_version = "2.23"
  16.  
  17. var advancedMode = false;
  18. var lastModified = false;
  19. var selectedLines = [];
  20. var wmechinit = false;
  21.  
  22. /* =========================================================================== */
  23. function highlightSegments(event) {
  24. if (!wmechinit) return;
  25. var showLocked = getId('_cbHighlightLocked').checked;
  26. var showToll = getId('_cbHighlightToll').checked;
  27. var showNoCity = getId('_cbHighlightNoCity').checked;
  28. var showAltName = getId('_cbHighlightAltName').checked;
  29. var showNoName = getId('_cbHighlightUnnamed').checked;
  30. var showOneWay = getId('_cbHighlightOneWay').checked;
  31. var showNoDirection = getId('_cbHighlightNoDirection').checked;
  32. var showRestrictions = getId('_cbHighlightRestrictions').checked;
  33. var showSpeedLimits = getId('_cbHighlightSpeedLimits').checked;
  34. var showAvgSpeedCams = getId('_cbHighlightAvgSpeedCams').checked;
  35. var plusRamps = getId('_cbHighlightPlusRampLimits').checked;
  36. var plusStreets = getId('_cbHighlightPlusStreetLimits').checked;
  37. var specificCity = getId('_cbHighlightCity').checked;
  38. var specificCityInvert = getId('_cbHighlightCityInvert').checked;
  39. var specificRoadType = getId('_cbHighlightRoadType').checked;
  40. var showNoHNs = getId('_cbHighlightNoHN').checked;
  41. var showRoutingPref = getId('_cbHighlightRoutingPref').checked;
  42. var showRecent = advancedMode ? getId('_cbHighlightRecent').checked : false;
  43. var specificEditor = getId('_cbHighlightEditor').checked;
  44.  
  45. // master switch when all options are off
  46. if (event && event.type && event.type == 'click') {
  47. if ( (showLocked | showToll | showNoCity | showNoName | showAltName | showOneWay | showNoDirection | showRestrictions
  48. | specificCity | specificEditor | specificRoadType | showRecent | showSpeedLimits | showAvgSpeedCams | showNoHNs
  49. ) == false) {
  50. for (var seg in Waze.model.segments.objects) {
  51. var segment = Waze.model.segments.get(seg);
  52. var line = getId(segment.geometry.id);
  53.  
  54. if (line === null) {
  55. continue;
  56. }
  57.  
  58. // turn off all highlights
  59. var opacity = line.getAttribute("stroke-opacity");
  60. if (opacity > 0.1 && opacity < 1) {
  61. line.setAttribute("stroke","#dd7700");
  62. line.setAttribute("stroke-opacity",0.001);
  63. line.setAttribute("stroke-dasharray", "none");
  64. }
  65. }
  66. return;
  67. }
  68. }
  69. var today = new Date();
  70. var recentDays;
  71. var selectedUserId = null;
  72. var selectedCityId = null;
  73. if (specificEditor) {
  74. var selectUser = getId('_selectUser');
  75. if (selectUser.selectedIndex >= 0)
  76. selectedUserId = selectUser.options[selectUser.selectedIndex].value;
  77. else
  78. specificEditor = false;
  79. }
  80.  
  81. if (specificCity) {
  82. var selectCity = getId('_selectCity');
  83. if (selectCity.selectedIndex >= 0)
  84. selectedCityId = selectCity.options[selectCity.selectedIndex].value;
  85. else
  86. specificCity = false;
  87. }
  88.  
  89. if (specificRoadType) {
  90. var selectRoadType = getId('_selectRoadType');
  91. if (selectRoadType.selectedIndex >= 0)
  92. selectedRoadType = selectRoadType.options[selectRoadType.selectedIndex].value;
  93. else
  94. specificRoadType = false;
  95. }
  96.  
  97. if (showRecent) {
  98. recentDays = getId('_numRecentDays').value;
  99. if (recentDays === undefined) recentDays = 0;
  100. }
  101.  
  102. // counters
  103. var numUserHighlighted = 0;
  104. var numCityHighlighted = 0;
  105.  
  106. for (var seg in Waze.model.segments.objects) {
  107. var segment = Waze.model.segments.get(seg);
  108. var attributes = segment.attributes;
  109. var line = getId(segment.geometry.id);
  110.  
  111. if (line === null) {
  112. continue;
  113. }
  114. var sid = attributes.primaryStreetID;
  115.  
  116. // check that WME hasn't highlighted this segment
  117. var opacity = line.getAttribute("stroke-opacity");
  118. var lineWidth = line.getAttribute("stroke-width");
  119. if (opacity == 1 || lineWidth == 9)
  120. continue;
  121. // turn off highlights when roads are no longer visible
  122. var roadType = attributes.roadType;
  123. if (Waze.map.zoom <= 3 && (roadType < 2 || roadType > 7) ) {
  124. if (opacity > 0.1) {
  125. line.setAttribute("stroke","#dd7700");
  126. line.setAttribute("stroke-opacity",0.001);
  127. line.setAttribute("stroke-dasharray", "none");
  128. }
  129. continue;
  130. }
  131.  
  132. // highlight all newly paved roads (or roads without any nodes)
  133. if (sid === null || (attributes.toNodeID === null && attributes.fromNodeID === null && roadType < 9)) {
  134. if (opacity < 0.1 && showNoName) {
  135. line.setAttribute("stroke","#f00");
  136. line.setAttribute("stroke-opacity",0.75);
  137. line.setAttribute("stroke-width", 10);
  138. }
  139. continue;
  140. }
  141. var street = Waze.model.streets.get(sid);
  142.  
  143. // get attributes for this segment
  144. var toll = attributes.fwdToll;
  145. var locked = attributes.lockRank !== null;
  146. var ranked = attributes.rank > 0 && attributes.lockRank === null;
  147. var noEdit = attributes.permissions == 0;
  148. var noName = (street != null) && street.isEmpty;
  149. var cityID = (street != null) && street.cityID;
  150. var noCity = false;
  151. var countryID = 0;
  152. if (cityID != null && Waze.model.cities.get(cityID) != null) {
  153. noCity = Waze.model.cities.get(cityID).attributes.isEmpty;
  154. countryID = Waze.model.cities.get(cityID).attributes.countryID;
  155. }
  156. var oneWay = ((attributes.fwdDirection + attributes.revDirection) == 1); // it is 1-way only if either is true
  157. var noDirection = (!attributes.fwdDirection && !attributes.revDirection); // Could use the .attribute.allowNoDirection?
  158. var hasRestrictions = (attributes.restrictions.length > 0);
  159. var updatedBy = attributes.updatedBy;
  160. var roundabout = attributes.junctionID !== null;
  161. var hasHouseNumbers = attributes.hasHNs;
  162. // get current state of the line
  163. var lineColor = line.getAttribute("stroke");
  164.  
  165. // default colours
  166. var newColor = "#dd7700";
  167. var newOpacity = 0.001;
  168. var newDashes = "none";
  169. var newWidth = 6;
  170.  
  171. // Recent Edits within X days, with decaying green opacity
  172. if (showRecent) {
  173. var editDays = (today.getTime() - attributes.createdOn) / 86400000;
  174. if (attributes.updatedOn !== null) {
  175. editDays = (today.getTime() - attributes.updatedOn) / 86400000;
  176. }
  177. if (recentDays >= 0 && editDays <= recentDays) {
  178. if ((updatedBy == selectedUserId) || (!specificEditor)) {
  179. //var heatScale = 0.75 / recentDays;
  180. //newColor = "#0f0";
  181. var shade = Math.floor(editDays * 128 / recentDays);
  182. newColor = "rgb(" + (0) + ", " + (255-shade) + ", " + (0) + ")";
  183. newOpacity = 0.5;
  184. //newOpacity = Math.min(0.999999, 1 - (editDays * heatScale));
  185. }
  186. }
  187. }
  188.  
  189. // Toll = Dashed
  190. else if (toll && showToll) {
  191. newColor = "#00f";
  192. newOpacity = 0.5;
  193. newDashes = "10 10";
  194. }
  195.  
  196. // No Edit = Black
  197. else if (noEdit && showLocked) {
  198. newColor = "#000";
  199. newOpacity = 0.75;
  200. newWidth = 3;
  201. }
  202.  
  203. // Locked = Red
  204. else if (locked && showLocked) {
  205. newColor = "#f00";
  206. newWidth = 6;
  207. newOpacity = 0.2 * Math.min(5, attributes.lockRank);
  208. }
  209.  
  210. else if (ranked && showLocked) {
  211. newColor = "#f00";
  212. newWidth = 6;
  213. newDashes = "2 8";
  214. newOpacity = 0.2 * Math.min(5, attributes.rank);
  215. }
  216.  
  217. else if (hasRestrictions && showRestrictions) {
  218. newColor = "#909";
  219. newDashes = "10 10";
  220. newOpacity = 0.5;
  221. }
  222.  
  223. // alternate names
  224. else if (showAltName && attributes.streetIDs.length > 0) {
  225. newColor = "#9C0";
  226. newOpacity = 0.75;
  227. if (noName) {
  228. newDashes = "10 10";
  229. }
  230. }
  231.  
  232. // No Speed Limits = Orange
  233. else if (showSpeedLimits && (plusStreets && attributes.roadType == 1 || plusRamps && attributes.roadType == 4 || attributes.roadType > 1 && attributes.roadType != 4)
  234. && attributes.roadType < 8 && attributes.roadType != 5
  235. && (plusStreets || attributes.junctionID == null)
  236. && ((attributes.fwdDirection && (attributes.fwdMaxSpeed == null || attributes.fwdMaxSpeedUnverified)) ||
  237. (attributes.revDirection && (attributes.revMaxSpeed == null || attributes.revMaxSpeedUnverified)) )) {
  238. newColor = "#f80";
  239. newOpacity = 0.8;
  240. newWidth = 4;
  241. }
  242. else if (showAvgSpeedCams && (attributes.fwdFlags & 1 || attributes.revFlags & 1)) {
  243. newColor = "#00f";
  244. newOpacity = 0.4;
  245. newWidth = 4;
  246. }
  247.  
  248. // Unnamed (No Name) = Orange
  249. // except roundabouts and non-Streets
  250. else if (noName && showNoName && !roundabout && attributes.roadType < 8) {
  251. newColor = "#fb0";
  252. newOpacity = 0.6;
  253. }
  254.  
  255. // No City = Gray
  256. else if (noCity && showNoCity) {
  257. newColor = "#888";
  258. newOpacity = 0.5;
  259. }
  260.  
  261. // No Direction = Cyan
  262. else if (noDirection && showNoDirection) {
  263. newColor = "#0ff";
  264. newOpacity = 0.3;
  265. newWidth = 4;
  266. }
  267.  
  268. // One Way = Blue
  269. else if (oneWay && showOneWay) {
  270. newColor = "#00f";
  271. newOpacity = 0.4;
  272. newWidth = 4;
  273. }
  274.  
  275. // segment with special flags
  276. else if (specificRoadType && (selectedRoadType & 64) > 0) {
  277. if (selectedRoadType == 64 && attributes.flags > 0) {
  278. newColor = "#909";
  279. newOpacity = 0.5;
  280. newWidth = 4;
  281. }
  282. // - tunnel
  283. else if (selectedRoadType == 65 && attributes.flags & 1) {
  284. newColor = "#909";
  285. newOpacity = 0.5;
  286. newWidth = 4;
  287. }
  288. // - unpaved
  289. else if (selectedRoadType == 66 && attributes.flags & 16) {
  290. newColor = "#909";
  291. newOpacity = 0.5;
  292. newWidth = 4;
  293. }
  294. }
  295.  
  296. // selected road type = purple
  297. else if (specificRoadType && attributes.roadType == selectedRoadType) {
  298. newColor = "#909";
  299. newOpacity = 0.5;
  300. newWidth = 4;
  301. }
  302.  
  303. // special road types: non-drivable / non-routable
  304. else if (specificRoadType && selectedRoadType == 98 && nonRoutableTypes.contains(attributes.roadType)) {
  305. newColor = "#909";
  306. newOpacity = 0.5;
  307. newWidth = 4;
  308. }
  309. else if (specificRoadType && selectedRoadType == 99 && nonDrivableTypes.contains(attributes.roadType)) {
  310. newColor = "#909";
  311. newOpacity = 0.5;
  312. newWidth = 4;
  313. }
  314.  
  315. // highlight roads with a routing preferrence set
  316. else if (showRoutingPref && attributes.routingRoadType != null) {
  317. newColor = "#0ff";
  318. newOpacity = 0.5;
  319. newWidth = 6;
  320. }
  321. // highlight roads with no house numbers (except Roundabouts, Freeways, Ramps and Walking Trails)
  322. else if (!hasHouseNumbers && showNoHNs && attributes.junctionID == null && attributes.roadType < 8 && (attributes.roadType < 3 || attributes.roadType > 5)) {
  323. newColor = "#800000";
  324. newOpacity = 0.5;
  325. newDashes = "10 10";
  326. }
  327. // highlight segments by selected user, unless already highlighted
  328. if (specificEditor && !showRecent) {
  329. if (updatedBy == selectedUserId && newColor == "#dd7700") {
  330. newColor = "#00ff00";
  331. newOpacity = 0.5;
  332. numUserHighlighted++;
  333. }
  334. else if (selectedUserId < -1 && updatedBy != -selectedUserId && newColor == "#dd7700") {
  335. newColor = "#00ff00";
  336. newOpacity = 0.5;
  337. numUserHighlighted++;
  338. }
  339. else if (updatedBy != selectedUserId) {
  340. newColor = "#dd7700";
  341. newOpacity = 0.001;
  342. newDashes = "none";
  343. }
  344. }
  345.  
  346. // highlight segments by selected City, unless already highlighted
  347. // if city is only on an alternate street highlight it with dashes
  348. if (specificCity) {
  349. var altCityMatch = false;
  350. var specificCityMatch = (cityID == selectedCityId);
  351. if (specificCityInvert)
  352. specificCityMatch = (cityID != selectedCityId && !noCity);
  353.  
  354. if (!specificCityMatch) {
  355. // look for matching city in alternate streets
  356. for (var i in attributes.streetIDs) {
  357. var streetID = attributes.streetIDs[i];
  358. var currentStreet = Waze.model.streets.get(streetID);
  359. if (currentStreet == null)
  360. continue;
  361. var cityMatch = (currentStreet.cityID == selectedCityId);
  362. if (specificCityInvert)
  363. cityMatch = !cityMatch
  364. if (cityMatch) {
  365. altCityMatch = true;
  366. break;
  367. }
  368. }
  369. }
  370.  
  371. if (specificCityMatch && (newColor == "#dd7700" || newColor == "#888")) {
  372. newColor = "#ff0";
  373. newOpacity = 0.75;
  374. newDashes = "none";
  375. numCityHighlighted++;
  376. } else if (altCityMatch && (newColor == "#dd7700" || newColor == "#888")) {
  377. newColor = "#ffff01";
  378. newOpacity = 0.75;
  379. newDashes = "10 10";
  380. newWidth = 6;
  381. numCityHighlighted++;
  382. } else if (!specificCityMatch && !altCityMatch && !noCity) {
  383. newColor = "#dd7700";
  384. newOpacity = 0.001;
  385. newDashes = "none";
  386. }
  387. }
  388.  
  389. // if colour has changed, update the line attributes
  390. if (lineColor != newColor) {
  391. line.setAttribute("stroke", newColor);
  392. line.setAttribute("stroke-opacity", newOpacity);
  393. line.setAttribute("stroke-dasharray", newDashes);
  394. if (newColor != "#dd7700") { //default
  395. line.setAttribute("stroke-width", newWidth);
  396. } else {
  397. line.setAttribute("stroke-width", 6);
  398. }
  399. }
  400. } // end of loop
  401. numUserHighlightedText = getId('_numUserHighlighted');
  402. if (specificEditor)
  403. numUserHighlightedText.innerHTML = ' = ' + numUserHighlighted;
  404. else
  405. numUserHighlightedText.innerHTML = '';
  406.  
  407. numCityHighlightedText = getId('_numCityHighlighted');
  408. if (specificCity)
  409. numCityHighlightedText.innerHTML = ' = ' + numCityHighlighted;
  410. else
  411. numCityHighlightedText.innerHTML = '';
  412. } // end of function
  413.  
  414. function highlightPlaces(event) {
  415. if (!wmechinit) return;
  416. if (typeof Waze.model.venues == "undefined") {
  417. return;
  418. }
  419. if (Waze.model.active == false) {
  420. return;
  421. }
  422. // refreshing, reset places to original style
  423. if (event && event.type && /click|change/.test(event.type)) {
  424. for (var mark in Waze.model.venues.objects) {
  425. var venue = Waze.model.venues.get(mark);
  426. var poly = getId(venue.geometry.id);
  427. if (poly !== null && poly.getAttribute("stroke-opacity") == 0.987) {
  428. if (venue.isPoint()) {
  429. poly.setAttribute("stroke","white");
  430. } else {
  431. poly.setAttribute("stroke","#ca9ace");
  432. poly.setAttribute("stroke-width",2);
  433. poly.setAttribute("stroke-dash-array","none");
  434. }
  435. poly.setAttribute("fill","#c290c6");
  436. poly.setAttribute("stroke-opacity", 1)
  437. }
  438. }
  439. }
  440.  
  441. // if option is disabled, stop now
  442. if (!getId('_cbHighlightPlaces').checked) {
  443. if (event && event.type && event.type == 'click') {
  444. getId('_cbHighlightLockedPlaces').disabled = true;
  445. getId('_cbHighlightIncompletePlaces').disabled = true;
  446. }
  447. return;
  448. } else {
  449. if (event && event.type && event.type == 'click') {
  450. getId('_cbHighlightLockedPlaces').disabled = false;
  451. getId('_cbHighlightIncompletePlaces').disabled = false;
  452. }
  453. }
  454. var showLocked = getId('_cbHighlightLockedPlaces').checked;
  455. var showIncomplete = getId('_cbHighlightIncompletePlaces').checked;
  456. var specificCity = getId('_cbHighlightCity').checked;
  457. var specificCityInvert = getId('_cbHighlightCityInvert').checked;
  458. var showRecent = advancedMode ? getId('_cbHighlightRecent').checked : false;
  459.  
  460. if (specificCity) {
  461. var selectCity = getId('_selectCity');
  462. if (selectCity.selectedIndex >= 0) {
  463. selectedCityId = selectCity.options[selectCity.selectedIndex].value;
  464. } else
  465. specificCity = false;
  466. }
  467.  
  468. var specificEditor = getId('_cbHighlightEditor').checked;
  469. if (specificEditor) {
  470. var selectEditor = getId('_selectUser');
  471. var selectedEditorId = 0;
  472. if (selectEditor.selectedIndex >= 0) {
  473. selectedEditorId = selectEditor.options[selectEditor.selectedIndex].value;
  474. } else
  475. specificEditor = false;
  476. }
  477.  
  478. if (showRecent) {
  479. recentDays = getId('_numRecentDays').value;
  480. if (recentDays === undefined) recentDays = 0;
  481. if (recentDays == 0) showRecent = false;
  482. }
  483.  
  484. var updates = 0;
  485. for (var mark in Waze.model.venues.objects) {
  486. var venue = Waze.model.venues.get(mark);
  487. var poly = getId(venue.geometry.id);
  488. // check that WME hasn't highlighted this object already
  489. if (poly == null || mark.state == "Update" || venue.selected) {
  490. continue;
  491. }
  492.  
  493. // if highlighted by mouse over, skip this one
  494. if (poly.getAttribute("fill") == poly.getAttribute("stroke")) {
  495. continue;
  496. }
  497. // if already highlighted by us, skip
  498. if (poly.getAttribute("stroke-opacity") == 0.987) {
  499. continue;
  500. }
  501. // flag this venue as highlighted so we don't update it next time
  502. poly.setAttribute("stroke-opacity", 0.987);
  503. updates++;
  504.  
  505. var categories = venue.attributes.categories;
  506. if (showIncomplete) {
  507. venueStreet = Waze.model.streets.get(venue.attributes.streetID);
  508. var incomplete = false;
  509. var colorhilite = false;
  510. // check for missing venue name
  511. if (venue.attributes.name == null || venue.attributes.name == "") {
  512. incomplete = !venue.attributes.residential;
  513. colorhilite = true;
  514. }
  515. // check for missing street name
  516. if (venueStreet == null || venueStreet.name == null || venueStreet.name == "") {
  517. incomplete = true;
  518. colorhilite = true;
  519. }
  520. // check for missing house number
  521. else if (venue.attributes.residential && venue.attributes.houseNumber == null) {
  522. incomplete = true;
  523. colorhilite = true;
  524. }
  525. // check for category group used as category
  526. else if (categories.length == 0
  527. || categories.indexOf("CAR_SERVICES") > -1
  528. || categories.indexOf("TRANSPORTATION") > -1
  529. || categories.indexOf("PROFESSIONAL_AND_PUBLIC") > -1
  530. || categories.indexOf("SHOPPING_AND_SERVICES") > -1
  531. || categories.indexOf("FOOD_AND_DRINK") > -1
  532. || categories.indexOf("CULTURE_AND_ENTERTAINMENT") > -1
  533. || categories.indexOf("OTHER") > -1
  534. || categories.indexOf("LODGING") > -1
  535. || categories.indexOf("OUTDOORS") > -1
  536. || categories.indexOf("NATURAL_FEATURES") > -1) {
  537. incomplete = (venue.attributes.lockRank == 0);
  538. }
  539. else if (typeof venue.attributes.externalProviderIDs === 'undefined' || venue.attributes.externalProviderIDs.length === 0) {
  540. incomplete = true;
  541. }
  542. if (incomplete &&
  543. (categories.indexOf("JUNCTION_INTERCHANGE") > -1
  544. || categories.indexOf("CANAL") > -1
  545. || categories.indexOf("RIVER_STREAM") > -1
  546. || categories.indexOf("SEA_LAKE_POOL") > -1
  547. || categories.indexOf("PARK") > -1
  548. || categories.indexOf("SWAMP_MARSH") > -1
  549. || categories.indexOf("FOREST_GROVE") > -1
  550. || categories.indexOf("GOLF_COURSE") > -1) ) {
  551. incomplete = false;
  552. colorhilite = false;
  553. }
  554. if (incomplete) {
  555. if (colorhilite) {
  556. highlightAPlace(venue, "orange", "white");
  557. }
  558. if (venue.isPoint())
  559. poly.setAttribute("stroke-dasharray", "3 3");
  560. else {
  561. poly.setAttribute("stroke-dasharray", "3 6");
  562. poly.setAttribute("stroke-width", "3");
  563. }
  564. }
  565. }
  566.  
  567. // highlight places which have the City field set in the address = yellow
  568. if (specificCity) {
  569. if (venue.attributes.streetID === undefined) continue;
  570. venueStreet = Waze.model.streets.get(venue.attributes.streetID);
  571. if (venueStreet === undefined) continue;
  572. selectedCityMatch = (specificCity && venueStreet.cityID == selectedCityId);
  573. if (specificCityInvert) selectedCityMatch = !selectedCityMatch;
  574.  
  575. if (selectedCityMatch) {
  576. highlightAPlace(venue, "#cc0", "#ff8");
  577. continue;
  578. }
  579. }
  580. // highlight places which have been edited by selected editor = green
  581. if (specificEditor) {
  582. var selectedEditorMatch = false
  583. if (selectedEditorId >= -1) {
  584. selectedEditorMatch = (selectedEditorId == venue.attributes.createdBy);
  585. if (typeof venue.attributes.updatedBy != 'undefined') {
  586. selectedEditorMatch = (selectedEditorId == venue.attributes.updatedBy);
  587. }
  588. }
  589. else {
  590. selectedEditorMatch = (selectedEditorId != -venue.attributes.createdBy);
  591. if (typeof venue.attributes.updatedBy != 'undefined') {
  592. selectedEditorMatch = (selectedEditorId != -venue.attributes.updatedBy);
  593. }
  594. }
  595. if (selectedEditorMatch) {
  596. highlightAPlace(venue, "#0f0", "#8f8");
  597. continue;
  598. }
  599. }
  600. // highlight places that have been edited recently
  601. if (showRecent) {
  602. var today = new Date();
  603. var editDays = (today.getTime() - venue.attributes.createdOn) / 86400000;
  604. if (typeof venue.attributes.updatedOn != 'undefined') {
  605. editDays = (today.getTime() - venue.attributes.updatedOn) / 86400000;
  606. }
  607. if (editDays <= recentDays) {
  608. var shade = Math.floor(editDays * 128 / recentDays);
  609. var colour = "rgb(" + (0) + ", " + (255-shade) + ", " + (0) + ")";
  610. highlightAPlace(venue, colour, colour);
  611. continue;
  612. }
  613. }
  614. // residential = cyan edges, like house numbers
  615. if (venue.attributes.residential) {
  616. highlightAPlace(venue, "#44afcf", "4ac");
  617. }
  618. // gas station = orange
  619. else if (categories.indexOf("GAS_STATION") > -1) {
  620. highlightAPlace(venue, "#f90", "#f91");
  621. }
  622.  
  623. // parking lot = cyan
  624. else if (categories.indexOf("PARKING_LOT") > -1) {
  625. catAttribs = venue.attributes.categoryAttributes["PARKING_LOT"];
  626. if (catAttribs == null || catAttribs.parkingType == null) {
  627. highlightAPlace(venue, "#099", "#0cc");
  628. poly.setAttribute("stroke-dasharray", "3 6");
  629. }
  630. else if (catAttribs.parkingType == "PUBLIC") {
  631. highlightAPlace(venue, "#090", "#0cc");
  632. }
  633. else if (catAttribs.parkingType == "RESTRICTED") {
  634. highlightAPlace(venue, "#aa0", "#0cc");
  635. }
  636. else if (catAttribs.parkingType == "PRIVATE") {
  637. highlightAPlace(venue, "#a50", "#0cc");
  638. }
  639. }
  640.  
  641. // water = blue
  642. else if (categories.indexOf("RIVER_STREAM") > -1 ||
  643. categories.indexOf("CANAL") > -1 ||
  644. categories.indexOf("SEA_LAKE_POOL") > -1) {
  645. highlightAPlace(venue, "#06c", "#09f");
  646. poly.setAttribute("stroke-dasharray", "none");
  647. }
  648.  
  649. // park/grass/trees = green
  650. else if (!showRecent && !specificEditor && (
  651. categories.indexOf("PARK") > -1 ||
  652. categories.indexOf("SWAMP_MARSH") > -1 ||
  653. categories.indexOf("FOREST_GROVE") > -1 ||
  654. categories.indexOf("GOLF_COURSE") > -1) ) {
  655. highlightAPlace(venue, "#0b0", "#4f4");
  656. poly.setAttribute("stroke-dasharray", "none");
  657. }
  658. // locked venues have red border (overrides all other options)
  659. if (showLocked && venue.attributes.lockRank > 0) {
  660. poly.setAttribute("stroke", "red");
  661. }
  662. } // for
  663. //if (updates > 0)
  664. // getId("wmedebug").innerText = updates;
  665. }
  666.  
  667. function highlightAPlace(venue, fg, bg) {
  668. var poly = getId(venue.geometry.id);
  669. if (venue.isPoint()) {
  670. poly.setAttribute("fill", fg);
  671. }
  672.  
  673. else { // area
  674. poly.setAttribute("stroke", fg);
  675. poly.setAttribute("fill", bg);
  676. }
  677. }
  678.  
  679. // used when clicking an option that affects both Segments and Places
  680. function highlightSegmentsAndPlaces(event) {
  681. if (!wmechinit) return;
  682.  
  683. highlightSegments(event);
  684. highlightPlaces(event);
  685. }
  686.  
  687. function highlightBadNodes() {
  688. if (!wmechinit || Waze.map.zoom <= 3 || !advancedMode)
  689. return true;
  690.  
  691. var showTurns = advancedMode ? getId('_cbHighlightTurns').checked : false;
  692. var showRestrictions = getId('_cbHighlightRestrictions').checked;
  693.  
  694. for (var currentNode in Waze.model.nodes.objects){
  695. var node = Waze.model.nodes.get(currentNode);
  696. var nodeAttr = node.attributes;
  697. if (node === undefined) continue;
  698.  
  699. var numRestrictions = 0;
  700. var numSoftTurns = 0;
  701. var numUTurns = 0;
  702. var segment1, segment2, seg1Attr, seg2Attr;
  703.  
  704. // ignore dead-end nodes
  705. if (nodeAttr.segIDs.length <= 1) {
  706. continue;
  707. }
  708.  
  709. for (var j = 0; j < nodeAttr.segIDs.length; j++){
  710. segment1 = Waze.model.segments.get(node.attributes.segIDs[j]);
  711. seg1Attr = segment1.attributes;
  712. // count restictions
  713. if (showRestrictions) {
  714. if (nodeAttr.id == seg1Attr.fromNodeID){
  715. if (seg1Attr.fromRestrictions){
  716. for (key in seg1Attr.fromRestrictions){
  717. numRestrictions++;
  718. }
  719. }
  720. }
  721. if (nodeAttr.id == seg1Attr.toNodeID){
  722. if (seg1Attr.toRestrictions){
  723. for (key in seg1Attr.toRestrictions){
  724. numRestrictions++;
  725. }
  726. }
  727. }
  728. }
  729. if (showTurns && majorRoadTypes.indexOf(seg1Attr.roadType) != -1) {
  730. // highlight U-turns
  731. if(segment1.isTurnAllowed(segment1, node)){
  732. numUTurns++;
  733. }
  734.  
  735. // highlight soft-turns
  736. if (nodeAttr.id == seg1Attr.fromNodeID){
  737. var nodeLocked = (seg1Attr.revTurnsLocked);
  738. } else if (nodeAttr.id == seg1Attr.toNodeID){
  739. var nodeLocked = (seg1Attr.fwdTurnsLocked);
  740. }
  741. if (nodeLocked === false){
  742. numSoftTurns++;
  743. }
  744. }
  745. }
  746. var newColor = null;
  747. if (numUTurns > 0) newColor = "#0ff"; // cyan
  748. if (numSoftTurns > 0) newColor = "#ff0"; // yellow
  749. if (numRestrictions > 0) newColor = "#909"; // purple
  750.  
  751. var circle = getId(nodeAttr.geometry.id);
  752. if (newColor != null && circle != null) {
  753. opacity = circle.getAttribute("fill-opacity");
  754. if (opacity < 0.1) {
  755. circle.setAttribute("fill-opacity", 0.75);
  756. circle.setAttribute("fill", newColor);
  757. }
  758. }
  759. }
  760. return true;
  761. }
  762.  
  763. // add logged in user to drop-down list
  764. function initUserList() {
  765. if (!advancedMode) return;
  766.  
  767. var thisUser = Waze.loginManager.user;
  768. if (thisUser === null) return;
  769.  
  770. var selectUser = getId('_selectUser');
  771. var usrOption = document.createElement('option');
  772. var usrRank = thisUser.normalizedLevel;
  773. var usrText = document.createTextNode(thisUser.userName + " (" + usrRank + ")");
  774. usrOption.setAttribute('value',thisUser.id);
  775. usrOption.appendChild(usrText);
  776. selectUser.appendChild(usrOption);
  777. console.info("WME Highlights: Init User list: " + thisUser.userName);
  778. }
  779.  
  780. // add current city in to drop-down list
  781. function initCityList() {
  782. var thisCity = Waze.model.segments.topCityID;
  783. if (thisCity === null) return;
  784. var thisName = Waze.model.cities.get(thisCity).attributes.name;
  785.  
  786. var selectCity = getId('_selectCity');
  787. var cityOption = document.createElement('option');
  788. var cityText = document.createTextNode(thisName);
  789. cityOption.appendChild(cityText);
  790. cityOption.setAttribute('value',thisCity);
  791. selectCity.appendChild(cityOption);
  792. console.info("WME Highlights: Init City list: " + thisName);
  793.  
  794. // stop listening for this event
  795. Waze.model.events.unregister("mergeend", null, initCityList);
  796. }
  797.  
  798. // populate drop-down list of editors
  799. function updateUserList() {
  800. // update list of users - for high zoom and AMs only
  801. if (!advancedMode)
  802. return;
  803.  
  804. var selectUser = getId('_selectUser');
  805. var numUsers = Waze.model.users.objects.length;
  806. if (numUsers === 0)
  807. return;
  808.  
  809. // preserve current selection
  810. var currentId = null;
  811. if (selectUser.selectedIndex >= 0)
  812. currentId = selectUser.options[selectUser.selectedIndex].value;
  813.  
  814. // collect array of users who have edited segments
  815. var editorIds = [];
  816. for (var seg in Waze.model.segments.objects) {
  817. var segment = Waze.model.segments.get(seg);
  818. if (typeof segment == 'undefined')
  819. continue;
  820. var editedBy = segment.attributes.createdBy;
  821. if (typeof segment.attributes.updatedBy != 'undefined') {
  822. editedBy = segment.attributes.updatedBy;
  823. }
  824. if (editorIds.indexOf(editedBy) == -1)
  825. editorIds.push(editedBy);
  826. }
  827. // collect array of users who have edited places
  828. for (var ven in Waze.model.venues.objects) {
  829. var venue = Waze.model.venues.get(ven);
  830. if (typeof venue == 'undefined')
  831. continue;
  832. var editedBy = venue.attributes.createdBy;
  833. if (typeof venue.attributes.updatedBy != 'undefined') {
  834. editedBy = venue.attributes.updatedBy;
  835. }
  836. if (editorIds.indexOf(editedBy) == -1)
  837. editorIds.push(editedBy);
  838. }
  839. if (editorIds.length === 0)
  840. return;
  841.  
  842. // sort IDs by name
  843. var editorList = [];
  844. for (var i = 0; i < editorIds.length; i++) {
  845. var id = editorIds[i];
  846. var user = Waze.model.users.get(id);
  847. if (user === null || typeof user === "undefined" || typeof user.userName === "undefined")
  848. continue;
  849. var name = user.userName;
  850. editorList.push({ id: id, name: name});
  851. }
  852. editorList.sort(function (a, b) {
  853. return a.name.localeCompare(b.name);
  854. });
  855.  
  856. // reset list
  857. selectUser.options.length = 0;
  858.  
  859. // add all users in field of view
  860. for (var i = 0; i < editorList.length; i++) {
  861. var id = editorList[i].id;
  862. var user = Waze.model.users.get(id);
  863. if (user === null || typeof(user) === "undefined")
  864. continue;
  865.  
  866. var usrOption = document.createElement('option');
  867. var usrRank = user.normalizedLevel;
  868. var usrText = document.createTextNode(user.userName + " (" + usrRank + ")");
  869. if (currentId !== null && id == currentId)
  870. usrOption.setAttribute('selected',true);
  871. usrOption.setAttribute('value',id);
  872. usrOption.appendChild(usrText);
  873. selectUser.appendChild(usrOption);
  874. }
  875. var thisUser = Waze.loginManager.user;
  876. if (thisUser !== null) {
  877. var usrOption = document.createElement('option');
  878. var usrText = document.createTextNode("(all except me)");
  879. if (currentId !== null && -thisUser.id == currentId)
  880. usrOption.setAttribute('selected',true);
  881. usrOption.setAttribute('value',-thisUser.id);
  882. usrOption.appendChild(usrText);
  883. selectUser.appendChild(usrOption);
  884. }
  885. }
  886.  
  887. // populate drop-down list of Cities
  888. function updateCityList() {
  889. var selectCity = getId('_selectCity');
  890. var numCities = Waze.model.cities.objects.length;
  891.  
  892. if (numCities === 0)
  893. return;
  894.  
  895. // preserve current selection
  896. var currentId = null;
  897. if (selectCity.selectedIndex >= 0)
  898. currentId = selectCity.options[selectCity.selectedIndex].value;
  899.  
  900. // collect array of Cities
  901. var cityIds = [];
  902. var cityObjs = [];
  903.  
  904. //=========================================================================================
  905. // This new block of code checks the following assumed conditions:
  906. // * Every U.S. city should have an associated state
  907. // * Every 'No city' U.S. city should be properly numbered (not an orphan blank city)
  908. // * We only care about states if get.cities shows us close enough to the U.S. to matter
  909. // * Any non US's city state code should be 99 (None/other)
  910. //========================================================================================
  911.  
  912. // collect list if unique cities from the segments
  913. for (var sid in Waze.model.streets.objects) {
  914. var cid = Waze.model.streets.get(sid).cityID;
  915. var city = Waze.model.cities.get(cid).attributes;
  916. if (cityIds.indexOf(cid) == -1) {
  917. cityIds.push(cid);
  918. cityObjs.push({id: city.id, name: city.name, state: city.stateID, country: city.countryID});
  919. }
  920. }
  921.  
  922. if (cityIds.length === 0)
  923. return;
  924.  
  925. // reset list
  926. selectCity.options.length = 0;
  927.  
  928. // count how many (non empty) states there are here
  929. var numStates = 0
  930. for (var obj in Waze.model.states.objects) {
  931. state = Waze.model.states.get(obj);
  932. if (state.id != 1 && state.name != "")
  933. numStates++;
  934. }
  935.  
  936. // count how many countries there are here
  937. var numCountries = 0;
  938. for (var obj in Waze.model.countries.objects) {
  939. numCountries++;
  940. }
  941.  
  942. // add all cities in field of view
  943. cityObjs.sort(function(a,b) {return a.name.localeCompare(b.name)});
  944. for (var i = 0; i < cityObjs.length; i++) {
  945. var cityID = cityObjs[i].id;
  946. // "State-like CityIDs" to ignore. These are consistently over 100,000,000.
  947. if (cityID > 100000000) continue;
  948. var cityName = cityObjs[i].name;
  949. var stateID = cityObjs[i].state;
  950. var countryID = cityObjs[i].country;
  951.  
  952. if (countryID == 235) { // for U.S. only
  953. // 'No City' segments in the U.S. should have an assigned state.
  954. // This ID has a prescribed range. If not in this range, we get 'other' state pollution in map,
  955. // or a bogus blank city associated to the state.
  956.  
  957. if (cityName === "") {
  958. if (cityID >= 999900 && cityID <= 999999) {
  959. cityName = "No City";
  960. } else {
  961. cityName = "EMPTY CITY";
  962. }
  963. }
  964. }
  965.  
  966. else { // for non U.S. segments
  967. if (cityName === "") cityName = "No City";
  968. }
  969.  
  970. var stateObj = Waze.model.states.get(stateID);
  971. var countryObj = Waze.model.countries.get(countryID);
  972.  
  973. // State handling. All cities should have an associated state. Throw an error if not.
  974. if (numStates > 0) {
  975. // If more than one state, we're appending it. No brainer.
  976. if (numStates > 1) {
  977. // ... and, if one of those states is 'Other', that's an error. Report it.
  978. if (stateObj.id === 99) {
  979. cityName += ", " + "NO STATE";
  980. }
  981. // If we get here, the state ID should be fine. Append it.
  982. else {
  983. cityName += ", " + stateObj.name;
  984. }
  985. }
  986.  
  987. // If we have more than one country and are in the US, append the state for sanity.
  988. if (numStates == 1 && numCountries > 1) {
  989. cityName += ", " + stateObj.name;
  990. }
  991. }
  992.  
  993. // If we're on a non-US street, state should always be 99, 'Other/none'.
  994. // Append if this is the case. Otherwise don't add anything.
  995. else if (stateID != 99 && stateID > 1) {
  996. cityName += ", INVALID STATE";
  997. }
  998.  
  999. if (numCountries > 1) {
  1000. cityName += ", " + countryObj.name.replace('United States', 'U.S.');
  1001. }
  1002.  
  1003. // create option in select menu
  1004. var cityOption = document.createElement('option');
  1005. var cityText = document.createTextNode(cityName);
  1006.  
  1007. if (currentId !== null && cityID == currentId)
  1008. cityOption.setAttribute('selected',true);
  1009. cityOption.setAttribute('value',cityID);
  1010. cityOption.appendChild(cityText);
  1011. selectCity.appendChild(cityOption);
  1012. }
  1013. }
  1014.  
  1015. var RoadTypes = {
  1016. 1: "Streets",
  1017. 98: "Non-Routable Roads", // --------------
  1018. 108: "- Off Road / Not maintained",
  1019. 120: "- Parking Lot Road",
  1020. 117: "- Private Road",
  1021. 114: "- Ferry",
  1022. 199: "Non-Drivable Roads", // --------------
  1023. 210: "- Pedestrian Bw",
  1024. 205: "- Walking Trails",
  1025. 216: "- Stairway",
  1026. 219: "- Runway/Taxiway",
  1027. // 2: "Primary Street",
  1028. // 3: "Freeways",
  1029. // 4: "Ramps",
  1030. // 6: "Major Highway",
  1031. // 7: "Minor Highway",
  1032. // 18: "Railroad",
  1033. // 14: "Ferry',
  1034. 364: "Special Flags", // --------------
  1035. 365: "- Tunnel",
  1036. 366: "- Unpaved"
  1037. };
  1038.  
  1039. var majorRoadTypes = new Array(2, 3, 4, 6, 7);
  1040. var nonRoutableTypes = new Array(8, 20, 17);
  1041. var nonDrivableTypes = new Array(5, 10, 16, 18, 19, 14);
  1042.  
  1043. // populate drop-down list of editors
  1044. function populateRoadTypes() {
  1045. var selectRoadType = getId('_selectRoadType');
  1046.  
  1047. for (var id in RoadTypes) {
  1048. var type = RoadTypes[id]
  1049. var usrOption = document.createElement('option');
  1050. var usrText = document.createTextNode(type);
  1051. if (id == 1)
  1052. usrOption.setAttribute('selected',true);
  1053. usrOption.setAttribute('value',id % 100);
  1054. usrOption.appendChild(usrText);
  1055. selectRoadType.appendChild(usrOption);
  1056. }
  1057. }
  1058.  
  1059. // enable advanced options if user is logged in and at least an AM
  1060. function enableAdvancedOptions()
  1061. {
  1062. if (advancedMode) return;
  1063.  
  1064. if (typeof Waze == 'undefined')
  1065. Waze = unsafeWindow.Waze;
  1066.  
  1067. if (typeof Waze.loginManager == 'undefined')
  1068. Waze.loginManager = unsafeWindow.Waze.loginManager;
  1069.  
  1070. if (typeof Waze.loginManager == 'undefined')
  1071. Waze.loginManager = unsafeWindow.loginManager;
  1072.  
  1073. if (Waze.loginManager !== null && Waze.loginManager.isLoggedIn()) {
  1074. thisUser = Waze.loginManager.user;
  1075. if (thisUser !== null && (thisUser.normalizedLevel >= 3 || thisUser.isAreaManager)) {
  1076. Waze.loginManager.events.unregister("afterloginchanged", null, enableAdvancedOptions);
  1077. console.info('WME Highlights: Advanced Options enabled for ' + thisUser.userName);
  1078. getId('advancedOptions').style.display = 'block';
  1079. advancedMode = true;
  1080. initUserList();
  1081. initCityList();
  1082. }
  1083. }
  1084. }
  1085.  
  1086. /* helper function */
  1087. function getElementsByClassName(classname, node) {
  1088. if(!node) node = document.getElementsByTagName("body")[0];
  1089. var a = [];
  1090. var re = new RegExp('\\b' + classname + '\\b');
  1091. var els = node.getElementsByTagName("*");
  1092. for (var i=0,j=els.length; i<j; i++)
  1093. if (re.test(els[i].className)) a.push(els[i]);
  1094. return a;
  1095. }
  1096.  
  1097. function getId(node) {
  1098. return document.getElementById(node);
  1099. }
  1100.  
  1101. /* =========================================================================== */
  1102. function initialiseHighlights()
  1103. {
  1104. if (wmechinit) {
  1105. return;
  1106. }
  1107.  
  1108. // init shortcuts
  1109. if(!window.Waze.map)
  1110. {
  1111. window.console.warn("WME Color Highlights "
  1112. + ": waiting for WME...");
  1113. setTimeout(initialiseHighlights, 789);
  1114. return;
  1115. }
  1116. // check if sidebar is hidden
  1117. var sidebar = getId('sidebar');
  1118. if (sidebar.style.display == 'none') {
  1119. console.warn("WME Highlights: not logged in yet - will initialise at login");
  1120. Waze.loginManager.events.register("login", null, initialiseHighlights);
  1121. return;
  1122. }
  1123. // check that user-info section is defined
  1124. var userTabs = getId('user-info');
  1125. if (userTabs === null) {
  1126. console.warn("WME Highlights: editor not initialised yet - trying again in a bit...");
  1127. setTimeout(initialiseHighlights, 789);
  1128. }
  1129. console.group("WME Color Highlights: " + wmech_version);
  1130.  
  1131. // add new box to left of the map
  1132. var navTabs = getElementsByClassName('nav-tabs', userTabs)[0];
  1133. var tabContent = getElementsByClassName('tab-content', userTabs)[0];
  1134. var addon = document.createElement('section');
  1135. addon.id = "highlight-addon";
  1136.  
  1137. // highlight segements
  1138. var section = document.createElement('p');
  1139. section.style.paddingTop = "0px";
  1140. //section.style.textIndent = "16px";
  1141. section.id = "hiliteOptions";
  1142. section.innerHTML = '<b>Highlight Segments</b><br>'
  1143. + '<input type="checkbox" id="_cbHighlightLocked" title="Locked Segments" /> '
  1144. + '<span title="Dotted = Automatic Locks (if available)">Locks*</span> (Red)<br>'
  1145. + '<input type="checkbox" id="_cbHighlightToll" /> '
  1146. + 'Toll (Dashed)<br>'
  1147. + '<input type="checkbox" id="_cbHighlightAltName" /> '
  1148. + '<span title="Dotted = No Name">Alternate Name</span> (Lime)<br>'
  1149. + '<input type="checkbox" id="_cbHighlightSpeedLimits" /> '
  1150. + '<span title="Segments with unverified speed limits (Orange)">No Speed Limit</span>'
  1151. + ' <input type="checkbox" id="_cbHighlightPlusRampLimits" />&nbsp;+Ramps'
  1152. + ' <input type="checkbox" id="_cbHighlightPlusStreetLimits" />&nbsp;+Streets<br>'
  1153. + '<input type="checkbox" id="_cbHighlightAvgSpeedCams" /> '
  1154. + '<span title="Average Speed Camera Zone">Avg Speed Cams (Blue)<br></span>'
  1155. + '<input type="checkbox" id="_cbHighlightUnnamed" /> '
  1156. + 'No Name (Orange)<br>'
  1157. + '<input type="checkbox" id="_cbHighlightNoCity" /> '
  1158. + 'No City (Gray)<br>'
  1159. + '<input type="checkbox" id="_cbHighlightOneWay" /> '
  1160. + 'One Way (Blue)<br>'
  1161. + '<input type="checkbox" id="_cbHighlightNoDirection" /> '
  1162. + 'Unknown Direction (Cyan)<br>'
  1163. + '<input type="checkbox" id="_cbHighlightRestrictions" /> '
  1164. + 'Time/Vehicle Restrictions (Purple)<br>'
  1165. + '<input type="checkbox" id="_cbHighlightNoHN" /> '
  1166. + '<span title="excluding Freeways and Ramps">No House Numbers (Dashed Maroon)</span> <br />'
  1167. + '<input type="checkbox" id="_cbHighlightCity" /> '
  1168. + 'Filter by City (Yellow) &nbsp;'
  1169. + ' <input type="checkbox" id="_cbHighlightCityInvert" /> invert <br> '
  1170. + ' <select id="_selectCity" name="_selectCity" style="margin: 0 0 4px 16px"></select>'
  1171. + '<span id="_numCityHighlighted"></span><br>'
  1172. + '<input type="checkbox" id="_cbHighlightRoadType" /> Highlight a Road Type (Purple)<br> '
  1173. + ' <select id="_selectRoadType" name="_selectRoadType" style="margin: 0 0 4px 16px"></select><br>'
  1174. ;
  1175. addon.appendChild(section);
  1176.  
  1177. // advanced options
  1178. section = document.createElement('p');
  1179. section.style.paddingTop = "0px";
  1180. section.style.textIndent = "16px";
  1181. section.style.display = "none";
  1182. section.id = 'advancedOptions';
  1183. section.innerHTML = '<b>Advanced Options</b><br>'
  1184. + '<input type="checkbox" id="_cbHighlightRecent" /> Recently Edited (Green)<br> '
  1185. + ' <input type="number" min="0" max="365" size="3" id="_numRecentDays" style="margin: 0 0 4px 16px"/> days<br>'
  1186. + '<input type="checkbox" id="_cbHighlightEditor" /> Filter by Editor (Green)<br> '
  1187. + ' <select id="_selectUser" name="_selectUser" style="margin: 0 0 4px 16px"></select>'
  1188. + '<span id="_numUserHighlighted"></span><br>'
  1189. + '<input type="checkbox" id="_cbHighlightTurns" /> <span title="*Only on primary roads and above">Soft-turns and U-turns*</span><br>'
  1190. + '<input type="checkbox" id="_cbHighlightRoutingPref" /> Routing Preference (Cyan)<br>'
  1191. ;
  1192. addon.appendChild(section);
  1193.  
  1194. // highlight places
  1195. section = document.createElement('p');
  1196. section.id = "hilitePlaces";
  1197. section.innerHTML = '<input type="checkbox" id="_cbHighlightPlaces" /> <b title="'
  1198. + 'parks/trees = green, water = blue, parking lot = cyan, '
  1199. + 'everything else = pink">Highlight Places</b> '
  1200. + '<span id="wmedebug" style="color: gray"></span><br>'
  1201. + '<input type="checkbox" id="_cbHighlightLockedPlaces" /> Locked Places (Red)<br>'
  1202. + '<input type="checkbox" id="_cbHighlightIncompletePlaces" /> '
  1203. + '<span title="If blank name or street, or wrong category">Incomplete Places</span> (Dashed Orange)<br>'
  1204. ;
  1205. addon.appendChild(section);
  1206.  
  1207. if (/Chrome/.test(navigator.userAgent)) {
  1208. addon.innerHTML += '<b><a href="https://chrome.google.com/webstore/detail/wme-color-highlights/ijnldkoicbhinlgnoigchihmegdjobjc" target="_blank"><u>'
  1209. + 'WME Color Highlights</u></a></b> &nbsp; v' + wmech_version;
  1210. } else {
  1211. addon.innerHTML += '<b><a href="https://greasyfork.org/scripts/3206-wme-color-highlights" target="_blank"><u>'
  1212. + 'WME Color Highlights</u></a></b> &nbsp; v' + wmech_version;
  1213. + ' <a href="https://greasyfork.org/scripts/3206-wme-color-highlights" target="_blank">'
  1214. + '<img src="http://waze.cryosphere.co.uk/scripts/update.php?version=' + wmech_version + '" /></a>';
  1215. }
  1216.  
  1217. newtab = document.createElement('li');
  1218. newtab.innerHTML = '<a href="#sidepanel-highlights" data-toggle="tab">Highlight</a>';
  1219. // icon: <span class="fa fa-tint" title="Highlight"></span>
  1220. navTabs.appendChild(newtab);
  1221.  
  1222. addon.id = "sidepanel-highlights";
  1223. addon.className = "tab-pane";
  1224. tabContent.appendChild(addon);
  1225.  
  1226. // check for AM or CM, and unhide Advanced options
  1227. enableAdvancedOptions();
  1228.  
  1229. // always populate road types
  1230. populateRoadTypes();
  1231.  
  1232. // setup onclick handlers for instant update:
  1233. getId('_cbHighlightLocked').onclick = highlightSegments;
  1234. getId('_cbHighlightToll').onclick = highlightSegments;
  1235. getId('_cbHighlightUnnamed').onclick = highlightSegments;
  1236. getId('_cbHighlightNoCity').onclick = highlightSegments;
  1237. getId('_cbHighlightOneWay').onclick = highlightSegments;
  1238. getId('_cbHighlightNoDirection').onclick = highlightSegments;
  1239. getId('_cbHighlightRestrictions').onclick = highlightSegments;
  1240. getId('_cbHighlightSpeedLimits').onclick = highlightSegments;
  1241. getId('_cbHighlightPlusRampLimits').onclick = highlightSegments;
  1242. getId('_cbHighlightPlusStreetLimits').onclick = highlightSegments;
  1243. getId('_cbHighlightAvgSpeedCams').onclick = highlightSegments;
  1244. getId('_cbHighlightRoutingPref').onclick = highlightSegments;
  1245. getId('_cbHighlightNoHN').onclick = highlightSegments;
  1246.  
  1247. getId('_cbHighlightRecent').onclick = highlightSegmentsAndPlaces;
  1248. getId('_cbHighlightEditor').onclick = highlightSegmentsAndPlaces;
  1249. getId('_cbHighlightCity').onclick = highlightSegmentsAndPlaces;
  1250. getId('_cbHighlightCityInvert').onclick = highlightSegmentsAndPlaces;
  1251. getId('_cbHighlightRoadType').onclick = highlightSegments;
  1252.  
  1253. getId('_selectUser').onfocus = updateUserList;
  1254. getId('_selectUser').onchange = highlightSegmentsAndPlaces;
  1255.  
  1256. getId('_selectCity').onfocus = updateCityList;
  1257. getId('_selectCity').onchange = highlightSegmentsAndPlaces;
  1258.  
  1259. getId('_numRecentDays').onchange = highlightSegmentsAndPlaces;
  1260. getId('_selectRoadType').onchange = highlightSegments;
  1261.  
  1262. getId('_cbHighlightPlaces').onclick = highlightPlaces;
  1263. getId('_cbHighlightLockedPlaces').onclick = highlightPlaces;
  1264. getId('_cbHighlightIncompletePlaces').onclick = highlightPlaces;
  1265.  
  1266.  
  1267. // restore saved settings
  1268. if (localStorage.WMEHighlightScript) {
  1269. //console.debug("WME Highlights: loading options");
  1270. options = JSON.parse(localStorage.WMEHighlightScript);
  1271.  
  1272. getId('_cbHighlightLocked').checked = (options[1] % 2 == 1);
  1273. getId('_cbHighlightToll').checked = options[2];
  1274. getId('_cbHighlightUnnamed').checked = options[3];
  1275. getId('_cbHighlightNoCity').checked = options[4];
  1276. getId('_cbHighlightOneWay').checked = options[5];
  1277. getId('_cbHighlightNoDirection').checked = options[6];
  1278. getId('_cbHighlightCity').checked = options[15];
  1279. getId('_cbHighlightRoadType').checked = options[16];
  1280. getId('_selectRoadType').selectedIndex = options[17];
  1281. getId('_cbHighlightPlaces').checked = options[7];
  1282. getId('_cbHighlightRestrictions').checked = options[19];
  1283. getId('_cbHighlightLockedPlaces').checked = options[20]; //(options[1] > 1);
  1284. getId('_cbHighlightIncompletePlaces').checked = options[21];
  1285. getId('_cbHighlightAltName').checked = options[22];
  1286. getId('_cbHighlightSpeedLimits').checked = options[23];
  1287. getId('_cbHighlightPlusRampLimits').checked = options[26];
  1288. getId('_cbHighlightPlusStreetLimits').checked = options[24];
  1289. getId('_cbHighlightAvgSpeedCams').checked = options[27];
  1290. getId('_cbHighlightNoHN').checked = options[28];
  1291. if (options[12] === undefined) options[12] = 7;
  1292. getId('_cbHighlightRecent').checked = options[11];
  1293. getId('_numRecentDays').value = options[12];
  1294. getId('_cbHighlightEditor').checked = options[13];
  1295. getId('_cbHighlightTurns').checked = options[18];
  1296. getId('_cbHighlightRoutingPref').checked = options[25];
  1297. } else {
  1298. getId('_cbHighlightPlaces').checked = true;
  1299. getId('_cbHighlightTurns').checked = true;
  1300. }
  1301.  
  1302. if (typeof Waze.model.venues == "undefined") {
  1303. getId('_cbHighlightPlaces').checked = false;
  1304. getId('_cbHighlightPlaces').disabled = true;
  1305. }
  1306.  
  1307. if (!getId('_cbHighlightPlaces').checked) {
  1308. getId('_cbHighlightLockedPlaces').disabled = true;
  1309. getId('_cbHighlightIncompletePlaces').disabled = true;
  1310. }
  1311.  
  1312. // overload the WME exit function
  1313. saveHighlightOptions = function() {
  1314. if (localStorage) {
  1315. //console.debug("WME Highlights: saving options");
  1316. var options = [];
  1317.  
  1318. // preserve previous options which may get lost after logout
  1319. if (localStorage.WMEHighlightScript)
  1320. options = JSON.parse(localStorage.WMEHighlightScript);
  1321.  
  1322. options[1] = 1 * getId('_cbHighlightLocked').checked + 2 * getId('_cbHighlightLockedPlaces').checked;
  1323. options[2] = getId('_cbHighlightToll').checked;
  1324. options[3] = getId('_cbHighlightUnnamed').checked;
  1325. options[4] = getId('_cbHighlightNoCity').checked;
  1326. options[5] = getId('_cbHighlightOneWay').checked;
  1327. options[6] = getId('_cbHighlightNoDirection').checked;
  1328. options[7] = getId('_cbHighlightPlaces').checked;
  1329. options[15] = getId('_cbHighlightCity').checked;
  1330. options[16] = getId('_cbHighlightRoadType').checked;
  1331. options[17] = getId('_selectRoadType').selectedIndex;
  1332. options[19] = getId('_cbHighlightRestrictions').checked;
  1333. options[20] = getId('_cbHighlightLockedPlaces').checked;
  1334. options[21] = getId('_cbHighlightIncompletePlaces').checked;
  1335. options[22] = getId('_cbHighlightAltName').checked;
  1336. options[23] = getId('_cbHighlightSpeedLimits').checked;
  1337. options[24] = getId('_cbHighlightPlusStreetLimits').checked;
  1338. options[26] = getId('_cbHighlightPlusRampLimits').checked;
  1339. options[27] = getId('_cbHighlightAvgSpeedCams').checked;
  1340. options[28] = getId('_cbHighlightNoHN').checked;
  1341. if (advancedMode) {
  1342. options[11] = getId('_cbHighlightRecent').checked;
  1343. options[12] = getId('_numRecentDays').value;
  1344. options[13] = getId('_cbHighlightEditor').checked;
  1345. options[18] = getId('_cbHighlightTurns').checked;
  1346. options[25] = getId('_cbHighlightRoutingPref').checked;
  1347. }
  1348.  
  1349. localStorage.WMEHighlightScript = JSON.stringify(options);
  1350. }
  1351. }
  1352. window.addEventListener("beforeunload", saveHighlightOptions, false);
  1353.  
  1354. // begin periodic updates
  1355. window.setInterval(highlightSegments,333);
  1356. window.setInterval(highlightBadNodes,444);
  1357. window.setInterval(highlightPlaces,500);
  1358.  
  1359. // trigger code when page is fully loaded, to catch any missing bits
  1360. window.addEventListener("load", function(e) {
  1361. var mapProblems = getId('map-problems-explanation')
  1362. if (mapProblems !== null) mapProblems.style.display = "none";
  1363. enableAdvancedOptions();
  1364. });
  1365.  
  1366. // register some events...
  1367. Waze.map.events.register("zoomend", null, highlightSegments);
  1368. Waze.map.events.register("zoomend", null, highlightBadNodes);
  1369. Waze.map.events.register("zoomend", null, highlightPlaces);
  1370.  
  1371. //Waze.loginManager.events.register("afterloginchanged", null, enableAdvancedOptions);
  1372. Waze.model.events.register("mergeend", null, initCityList);
  1373.  
  1374. Waze.app.modeController.model.bind('change:mode', onModeChange);
  1375.  
  1376. wmechinit = true;
  1377. console.groupEnd();
  1378. }
  1379.  
  1380. // recreate my tab when MTE mode is exited
  1381. function onModeChange(model, modeId) {
  1382. wmechinit = false;
  1383. if (modeId == 0) {
  1384. //initialiseHighlights(); // FIXME
  1385. }
  1386. }
  1387.  
  1388. /* engage! =================================================================== */
  1389. setTimeout(initialiseHighlights, 789);
  1390.  
  1391. })();
  1392. /* end ======================================================================= */