WME Speed

This script allows you to highlight various issues and properties of road segments.

  1. // ==UserScript==
  2. // @name WME Speed
  3. // @namespace WME_SPEED
  4. // @include https://*.waze.com/editor/*
  5. // @description This script allows you to highlight various issues and properties of road segments.
  6. // @version 0.0.4
  7. // @grant none
  8. // ==/UserScript==
  9.  
  10.  
  11. function wmeSpeedBootstrap()
  12. {
  13. var bGreasemonkeyServiceDefined = false;
  14.  
  15. try
  16. {
  17. if ("object" === typeof Components.interfaces.gmIGreasemonkeyService)
  18. {
  19. bGreasemonkeyServiceDefined = true;
  20. }
  21. }
  22. catch (err)
  23. {
  24. //Ignore.
  25. }
  26. if ( "undefined" === typeof unsafeWindow || ! bGreasemonkeyServiceDefined)
  27. {
  28. unsafeWindow = ( function ()
  29. {
  30. var dummyElem = document.createElement('p');
  31. dummyElem.setAttribute ('onclick', 'return window;');
  32. return dummyElem.onclick ();
  33. } ) ();
  34. }
  35. setTimeout(function() {
  36. wmeSpeedInit();
  37. }, 1500);
  38.  
  39. }
  40.  
  41. function wmeSpeedInit() {
  42. var version = "v0.0.4";
  43. //
  44. // CLASS DEFINITIONS FILE
  45. //
  46. var WME_SPEED_UNKNOWN = -987;
  47.  
  48. var FRONT_ABBREVS = ["S", "N", "E", "W"]
  49. var END_ABBREVS = ["Ave", "Blvd", "Cir", "Ct", "Dr", "Hts", "Ln", "Loop", "Pkwy", "Pl", "Rd", "Rdge", "Rte", "St", "Trl", "Way"]
  50. var InterstateRegEx = /^I-\d\d\d? /;
  51.  
  52. var ERROR_RGBA = 'rgba(187,0,0,0.7)'
  53. var ERROR_MODS = {color: "#B00", opacity: 0.7 };
  54.  
  55. function SelectSection(hdr, iD, slctns) {
  56. this.header = hdr;
  57. this.id = iD;
  58. this.selections = slctns;
  59. }
  60.  
  61. function hasRestrictions(segmentAttr) {
  62. return ((segmentAttr.fwdRestrictions != null && segmentAttr.fwdRestrictions.length > 0)
  63. || (segmentAttr.revRestrictions != null && segmentAttr.revRestrictions.length > 0))
  64. }
  65.  
  66. function getId(name) { return document.getElementById(name); }
  67.  
  68. function roadTypeToString(roadType) {
  69. switch(roadType) {
  70. case 1: return "Street"
  71. case 2: return "Primary Street"
  72. case 3: return "Freeway"
  73. case 4: return "Ramps"
  74. case 5: return "Walking Trail"
  75. case 6: return "Major Highway"
  76. case 7: return "Minor Highway"
  77. case 8: return "Dirt road"
  78. case 10: return "Pedestrian Bw"
  79. case 16: return "Stairway"
  80. case 17: return "Private Road"
  81. case 18: return "Railroad"
  82. case 19: return "Runway/Taxiway"
  83. case 20: return "Parking Lot Road"
  84. case 21: return "Service Road"
  85. default:
  86. return "Unknown";
  87. }
  88. }
  89.  
  90. function isTrafficRelevant(roadType) {
  91. switch(roadType) {
  92. //"Streets"
  93. case 1:
  94. //"Primary Street"
  95. case 2:
  96. //"Freeways",
  97. case 3:
  98. //"Ramps",
  99. case 4:
  100. //"Major Highway",
  101. case 6:
  102. //"Minor Highway",
  103. case 7:
  104. //"Service Road"
  105. case 21:
  106. return true;
  107. default:
  108. return false;
  109. }
  110. }
  111.  
  112. function isOneWay(segment) {
  113. return ((segment.attributes.fwdDirection + segment.attributes.revDirection) == 1);
  114. }
  115.  
  116. function isNoDirection(segment) {
  117. return ((segment.attributes.fwdDirection + segment.attributes.revDirection) == 0);
  118. }
  119.  
  120. function isInterstate(segment) {
  121. var sid = segment.attributes.primaryStreetID;
  122. if(sid) {
  123. var street = Waze.model.streets.get(sid);
  124. var streetName = street.name;
  125. if(streetName == null || streetName == "") {
  126. return false;
  127. }
  128. return segment.attributes.roadType == 3 && streetName.match(InterstateRegEx) != null;
  129. }
  130. return false;
  131. }
  132.  
  133. function getSegmentSpeed(segment) {
  134. var speedToUse = 0;
  135. if(typeof segment.attributes.fwdDirection === "undefined") {
  136. speedToUse = "NA"
  137. }
  138. else {
  139. var oneWay = isOneWay(segment);
  140. if (oneWay && segment.attributes.fwdDirection) {
  141. speedToUse = segment.attributes.fwdCrossSpeed;
  142. } else if (oneWay && segment.attributes.revDirection) {
  143. speedToUse = segment.attributes.revCrossSpeed;
  144. } else {
  145. // take average? we could do a max, or a min, or ...
  146. speedToUse = (segment.attributes.revCrossSpeed + segment.attributes.fwdCrossSpeed) / 2;
  147. }
  148. if (!isNaN(speedToUse)) {
  149. speedToUse *= 0.621;
  150. // convert from km/h to MPH
  151. speedToUse = Math.ceil(speedToUse / 5) * 5;
  152. // round up to the nearest 5 mph
  153. speedToUse = Math.round(speedToUse);
  154. // may not be necessary
  155. }
  156. }
  157. return speedToUse;
  158. }
  159.  
  160. // CLASS DEFINITIONS
  161. function LineBearing(dist, bear) {
  162. this.distance = dist;
  163. this.bearing = bear;
  164. }
  165.  
  166. function getDistance(p1, p2) {
  167.  
  168. var y1 = p1.y;
  169. var x1 = p1.x;
  170.  
  171. var y2 = p2.y;
  172. var x2 = p2.x;
  173.  
  174. var dLat = y2 - y1;
  175. var dLon = x2 - x1;
  176. var d = Math.sqrt(Math.pow(dLat, 2) + Math.pow(dLon, 2));
  177.  
  178. // http://mathforum.org/library/drmath/view/55417.html
  179. var bearing = 0;
  180. if (dLon > 0) {
  181. if (dLat > 0) {
  182. bearing = calcTan(dLon, dLat);
  183. }
  184. if (dLat < 0) {
  185. bearing = 180 - calcTan(-1 * dLon, dLat);
  186. }
  187. if (dLat == 0) {
  188. bearing = 90;
  189. }
  190. }
  191. if (dLon < 0) {
  192. if (dLat > 0) {
  193. bearing = -1 * calcTan(-1 * dLon, dLat);
  194. }
  195. if (dLat < 0) {
  196. bearing = calcTan(dLon, dLat) - 180;
  197. }
  198. if (dLat == 0) {
  199. bearing = 270;
  200. }
  201. }
  202. if (dLon == 0) {
  203. if (dLat > 0) {
  204. bearing = 0;
  205. }
  206. if (dLat < 0) {
  207. bearing = 180;
  208. }
  209. if (dLat == 0) {
  210. bearing = 0;
  211. }
  212. }
  213. bearing += 360;
  214. bearing = bearing % 360;
  215.  
  216. return new LineBearing(d, bearing);
  217.  
  218. }
  219.  
  220. function getComponentsProperties(comps) {
  221. var compSegs = [];
  222. for (var i = 1; i < comps.length; i++) {
  223. var p1 = compToPoint(comps[i - 1]);
  224. var p2 = compToPoint(comps[i]);
  225. var dist = getDistance(p1, p2);
  226. compSegs.push(dist);
  227. }
  228. return compSegs;
  229. }
  230.  
  231. function Point(x, y) {
  232. this.x = x;
  233. this.y = y;
  234. }
  235.  
  236. function compToPoint(comp) {
  237. return new Point(comp.x, comp.y);
  238. }
  239.  
  240. Point.prototype.getLineTo = function(p2) {
  241. var lat1 = this.latitude;
  242. var lon1 = this.longitude;
  243.  
  244. var lat2 = p2.latitude;
  245. var lon2 = p2.longitude;
  246.  
  247. var dLat = lat2 - lat1;
  248. var dLon = lon2 - lon1;
  249. var d = Math.sqrt(Math.pow(dLat, 2) + Math.pow(dLon, 2));
  250.  
  251. var bearing = 0;
  252. // North / South
  253. if (dLon == 0) {
  254. bearing = dLat < 0 ? 180 : 0;
  255. } else {
  256. bearing = (Math.tan(dLat / dLon) / (2 * Math.PI)) * 360;
  257. }
  258. // return new LineBearing(d, bearing);
  259. }
  260. function WazeStreet(streetId) {
  261. var street = Waze.model.streets.get(streetId);
  262. this.cityID = street.cityID;
  263. var city = Waze.model.cities.get(this.cityID);
  264. this.noCity = city == null || city.isEmpty;
  265. this.noName = street.isEmpty;
  266. this.state = this.noCity ? null : Waze.model.states.get(city.stateID);
  267. }
  268.  
  269. function WazeNode(nodeId) {
  270. this.id = nodeId;
  271. this.Node = Waze.model.nodes.objects[nodeId];
  272. this.attributes = this.Node.attributes;
  273. }
  274.  
  275. WazeNode.prototype.UTurnAllowed = function(segmentId) {
  276. if(typeof this.Node === "undefined") return false;
  277. var connections = this.Node.attributes.connections[segmentId + "," + segmentId];
  278. return (typeof connections !== "undefined");
  279. };
  280.  
  281. WazeNode.prototype.isDeadEnd = function() {
  282. if(typeof this.Node === "undefined") return false;
  283. return this.Node.attributes.segIDs.length < 2;
  284. };
  285.  
  286. function WazeLineSegment(segment) {
  287. this.id = segment.fid;
  288. this.geometry = segment.geometry;
  289. this.attributes = segment.attributes;
  290. var primStrId = this.attributes.primaryStreetID;
  291. this.primaryStreetInfo = new WazeStreet(primStrId);
  292. this.ToNode = this.attributes.toNodeID ? new WazeNode(this.attributes.toNodeID) : null;
  293. this.FromNode = this.attributes.fromNodeID ? new WazeNode(this.attributes.fromNodeID) : null;
  294. this.secondaryStreetInfos = [];
  295. if(this.attributes.streetIDs) {
  296. for(var secStrIdx = 0; secStrIdx < this.attributes.streetIDs.length; secStrIdx++) {
  297. this.secondaryStreetInfos[secStrIdx] = new WazeStreet(this.attributes.streetIDs[secStrIdx]);
  298. }
  299. }
  300. this.cityID = this.primaryStreetInfo.cityID;
  301. this.line = getId(segment.geometry.id);
  302. this.streetName = null;
  303. this.streetState = null;
  304. this.noName = this.primaryStreetInfo.noName;
  305. this.noCity = this.primaryStreetInfo.noCity;
  306. this.state = this.primaryStreetInfo.state;
  307. this.oneWay = ((this.attributes.fwdDirection + this.attributes.revDirection) == 1);
  308. // it is 1-way only if either is true
  309. this.noDirection = (!this.attributes.fwdDirection && !this.attributes.revDirection);
  310. // Could use the .attribute.allowNoDirection?
  311. this.updatedOn = new Date(this.attributes.updatedOn);
  312. this.updatedBy = this.attributes.updatedBy;
  313. this.fwdSpeed = Math.abs(this.attributes.fwdCrossSpeed);
  314. this.revSpeed = Math.abs(this.attributes.revCrossSpeed);
  315. this.length = this.attributes.length;
  316. this.roadType = this.attributes.roadType;
  317. this.segment = segment;
  318. }
  319.  
  320. WazeLineSegment.prototype.getStreetName = function() {
  321.  
  322. if (!this.streetName) {
  323. var sid = this.segment.attributes.primaryStreetID;
  324. var street = Waze.model.streets.get(sid);
  325. if (sid && street.name !== null) {
  326. this.streetName = street.name;
  327. } else {
  328. this.streetName = "";
  329. }
  330. }
  331. return this.streetName;
  332. };
  333.  
  334. WazeLineSegment.prototype.containsUTurn = function() {
  335. return this.ToNode.UTurnAllowed(this.id) || this.FromNode.UTurnAllowed(this.id);
  336. };
  337.  
  338. function WMEFunction(acheckboxId, aText) {
  339. this.checkboxId = acheckboxId;
  340. this.text = aText;
  341. }
  342.  
  343. WMEFunction.prototype.getCheckboxId = function() {
  344. return this.checkboxId;
  345. };
  346. WMEFunction.prototype.getBackground = function() {
  347. return '#fff';
  348. };
  349.  
  350. WMEFunction.prototype.build = function(checkValue) {
  351. var checkStr = checkValue ? "checked" : "";
  352. return '<input style="" type="checkbox" id="' + this.getCheckboxId() + '" ' + checkStr + '/> ' + this.text;
  353. };
  354. WMEFunction.prototype.init = function() {
  355. console.log("init");
  356. getId(this.getCheckboxId()).onclick = highlightAllSegments;
  357. };
  358. WMEFunction.prototype.getModifiedAttrs = function(wazeLineSegment) {
  359. return new Object();
  360. };
  361.  
  362. WMEFunction.prototype.getDetail = function(wazeLineSegment) {
  363. return;
  364. };
  365.  
  366. function WMEFunctionExtended(acheckboxId, aText) {
  367. WMEFunction.call(this, acheckboxId, aText);
  368. }
  369.  
  370. extend(WMEFunctionExtended.prototype, WMEFunction.prototype);
  371.  
  372. WMEFunctionExtended.prototype.getSelectId = function() {
  373. return this.getCheckboxId() + 'Select';
  374. }
  375.  
  376. WMEFunctionExtended.prototype.buildExtended = function() {
  377. return '';
  378. }
  379.  
  380. WMEFunctionExtended.prototype.build = function(checkValue) {
  381. return WMEFunction.prototype.build.call(this, checkValue) + '<br />' + this.buildExtended();
  382. };
  383.  
  384. WMEFunctionExtended.prototype.getSelectFieldChangeFunction = function() {
  385. var that = this;
  386. return function() {
  387. getId(that.getCheckboxId()).checked = "checked";
  388. highlightSegments();
  389. };
  390. };
  391.  
  392. function EventPublisher() {
  393. this.subscribers = [];
  394. }
  395.  
  396. EventPublisher.prototype = {
  397. subscribe : function(fn) {
  398. this.subscribers.push(fn);
  399. },
  400. unsubscribe : function(fn) {
  401. },
  402. post : function(thisObj) {
  403. for (var i = 0, j = this.subscribers.length; i < j; i++) {
  404. this.subscribers[i].call(thisObj);
  405. };
  406. }
  407. };
  408.  
  409. function HighlightSegmentMonitor() {
  410. var eventPublisher = new EventPublisher();
  411. var latestSegment = null;
  412. this.subscribe = function(fn) {
  413. eventPublisher.subscribe(fn);
  414. }
  415. this.updateLatestSegment = function(latest) {
  416. latestSegment = latest;
  417. eventPublisher.post(latest);
  418. }
  419. this.getLatestSegment = function() {
  420. return latestSegment;
  421. }
  422. }
  423.  
  424. var highlightSegmentMonitor = new HighlightSegmentMonitor();
  425.  
  426. //
  427. // UTILITY DEFINITIONS FILE
  428. //
  429.  
  430. //// UTIL FUNCTIONS
  431. function extend(target, source) {
  432. var hasOwnProperty = Object.prototype.hasOwnProperty;
  433. for (var propName in source) {
  434. // Invoke hasOwnProperty() with this = source
  435. if (hasOwnProperty.call(source, propName)) {
  436. target[propName] = source[propName];
  437. }
  438. }
  439. return target;
  440. }
  441.  
  442. if (!Array.prototype.filter)
  443. {
  444. Array.prototype.filter = function(fun /*, thisArg */)
  445. {
  446. "use strict";
  447.  
  448. if (this === void 0 || this === null)
  449. throw new TypeError();
  450.  
  451. var t = Object(this);
  452. var len = t.length >>> 0;
  453. if (typeof fun !== "function")
  454. throw new TypeError();
  455.  
  456. var res = [];
  457. var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
  458. for (var i = 0; i < len; i++)
  459. {
  460. if (i in t)
  461. {
  462. var val = t[i];
  463.  
  464. // NOTE: Technically this should Object.defineProperty at
  465. // the next index, as push can be affected by
  466. // properties on Object.prototype and Array.prototype.
  467. // But that method's new, and collisions should be
  468. // rare, so use the more-compatible alternative.
  469. if (fun.call(thisArg, val, i, t))
  470. res.push(val);
  471. }
  472. }
  473.  
  474. return res;
  475. };
  476. }
  477.  
  478. function getScaledHex(index, maximum, startColor, endColor) {
  479. if (index >= maximum) {
  480. index = maximum - 1;
  481. }
  482. var colorVal = startColor + ((endColor - startColor) * (index / (maximum - 1)));
  483.  
  484. colorVal = Math.round(colorVal);
  485.  
  486. // convert from decimal to hexadecimal
  487. var colorHex = colorVal.toString(16);
  488.  
  489. // pad the hexadecimal number if required
  490. if (colorHex.length < 2) {
  491. colorHex = "0" + colorHex;
  492. }
  493. return colorHex;
  494. }
  495.  
  496. function getScaledColour(index, maximum) {
  497. var blueHex = "00";
  498.  
  499. var startGreen = 0;
  500. var endGreen = 255;
  501.  
  502. var startRed = 255;
  503. var endRed = 0;
  504.  
  505. return "#" + getScaledHex(index, maximum, startRed, endRed) + getScaledHex(index, maximum, startGreen, endGreen) + blueHex;
  506. }
  507.  
  508. function generateTopDownGradient(top, bottom) {
  509. var stylizer = "background-color: " + top + ";"
  510. stylizer += "background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%," + top + "), color-stop(100%, " + bottom + "));";
  511. stylizer += "background-image: -webkit-linear-gradient(top, " + top + ", " + bottom + ");";
  512. stylizer += "background-image: -moz-linear-gradient(top, " + top + ", " + bottom + ");";
  513. stylizer += "background-image: -ms-linear-gradient(top, " + top + ", " + bottom + ");";
  514. stylizer += "background-image: -o-linear-gradient(top, " + top + ", " + bottom + ");";
  515. stylizer += "background-image: linear-gradient(top, " + top + ", " + bottom + ");";
  516. return stylizer;
  517. }
  518.  
  519. function padNumber(numDigits, number) {
  520. var startNum = Math.pow(10, numDigits) / 10;
  521. var numStr = "" + number;
  522. while(number < startNum && startNum > 1) {
  523. numStr = "0" + numStr;
  524. startNum /= 10;
  525. }
  526. return numStr;
  527. }
  528.  
  529. function dateToDateString(dateVal) {
  530. return "" + dateVal.getFullYear() + "/" + padNumber(2, dateVal.getMonth()+1) + "/" + padNumber(2, dateVal.getDate());
  531. }
  532.  
  533. function lengthToString(lengthInMeters) {
  534. return Math.round(lengthInMeters * 3.28084) + " ft"
  535. }
  536.  
  537. function calcTan(dLon, dLat) {
  538. return (Math.atan(dLon/dLat) / (2 * Math.PI)) * 360;
  539. }
  540. //
  541. // COMPONENT SELECTION CLASS
  542. //
  543. /** GEOMETRY **/
  544.  
  545. function getBearingDiff(bearing1, bearing2) {
  546. // normalize the first angle to 0, and subtract the same from the second;
  547. var normalizeAngle = bearing1;
  548. bearing1 -= normalizeAngle;
  549. var diffAngle = bearing2 - normalizeAngle;
  550.  
  551. if (diffAngle < -180) {
  552. diffAngle += 360;
  553. } else if (diffAngle > 180) {
  554. diffAngle -= 360;
  555. }
  556. return diffAngle;
  557. }
  558.  
  559. function rightTurn(bearing1, bearing2) {
  560. return getBearingDiff(bearing1, bearing2) > 0;
  561. }
  562.  
  563. var MIN_DISTANCE_BETWEEN_COMPONENTS = 1.5;
  564. var MIN_LENGTH_DIFF = 0.005;
  565.  
  566. function between(value, min, max) {
  567. if (max < min) {
  568. var temp = min;
  569. min = max;
  570. max = temp
  571. }
  572. var between = value > min && value < max;
  573. // console.log("between? " + min + " " + value + " " + max + " = " + between);
  574. return between;
  575. }
  576.  
  577. var ZIG_ZAG_MAX_DIST = 30;
  578. var ZIG_ZAG_MAX_ANGLE = 3;
  579. var negate_ZIG_ZAG_MAX_ANGLE = -1 * ZIG_ZAG_MAX_ANGLE;
  580. var MIN_ANGLE_DIFF = 0.7;
  581.  
  582. function subtleZigZags(segmentProperties) {
  583. // detect zig zagging...
  584. var segmentChain = [];
  585. for (var i = 0; i < segmentProperties.length; i++) {
  586. var currentSegment = segmentProperties[i];
  587. segmentChain.push(currentSegment);
  588. if (segmentChain.length < 3) {
  589. continue;
  590. }
  591. if (currentSegment.distance > ZIG_ZAG_MAX_DIST) {
  592. segmentChain = [];
  593. continue;
  594. }
  595. var origSegment = segmentChain[segmentChain.length - 3];
  596. var pastSegment = segmentChain[segmentChain.length - 2];
  597. var bearing1 = origSegment.bearing;
  598. var bearing2 = pastSegment.bearing;
  599. var bearing3 = currentSegment.bearing;
  600.  
  601. var bearDiff1 = getBearingDiff(bearing1, bearing2);
  602. var bearDiff2 = getBearingDiff(bearing2, bearing3);
  603.  
  604. if ((between(bearDiff1, 0, ZIG_ZAG_MAX_ANGLE) && between(bearDiff2, 0, negate_ZIG_ZAG_MAX_ANGLE)) || (between(bearDiff1, 0, negate_ZIG_ZAG_MAX_ANGLE) && between(bearDiff2, 0, ZIG_ZAG_MAX_ANGLE))) {
  605. return true;
  606. }
  607. }
  608. return false;
  609. }
  610.  
  611. function checkForLowAngles(segmentProperties) {
  612. if (segmentProperties.length < 2) {
  613. return;
  614. }
  615. for (var i = 0; i < segmentProperties.length - 1; i++) {
  616. var currentSegment = segmentProperties[i];
  617. var nextSegment = segmentProperties[i + 1];
  618. var bearing1 = currentSegment.bearing;
  619. var bearing2 = nextSegment.bearing;
  620. var bearDiff1 = getBearingDiff(bearing1, bearing2);
  621. if (Math.abs(bearDiff1) < MIN_ANGLE_DIFF) {
  622. return true;
  623. }
  624. }
  625. return false;
  626. }
  627.  
  628. // Check for subtle zig-zags on longer components where the end result of the zig-zag is almost nothing
  629.  
  630. // Check for sharp zig-zags on very short components where the end result of the zig-zag is almost nothing
  631.  
  632. // OR
  633.  
  634. // Check for issues when (angle / length) reaches a threshold. So sharp angles reach the threshold with small lengths;
  635.  
  636. // --
  637.  
  638. // Take the difference between the total sum and the sum of the components. Take the the differene to create an average distance per component. If that average exceeds a trheshoold...
  639.  
  640. // // //
  641.  
  642. // On major streets, checks to see that there aren't places where the street can't continue due to turn restrictions.
  643.  
  644. var highlightLowAngles = new WMEFunction("_cbHighlightLowAngles", "Low Angles");
  645. highlightLowAngles.getModifiedAttrs = function(wazeLineSegment) {
  646. var components = wazeLineSegment.geometry.components;
  647. if (components.length <= 2) {
  648. return new Object();
  649. }
  650. var foundIssue = false;
  651. var segmentProperties = getComponentsProperties(wazeLineSegment.geometry.components);
  652.  
  653. if (checkForLowAngles(segmentProperties)) {
  654. foundIssue = true;
  655. }
  656.  
  657. var modifications = new Object();
  658. if (foundIssue) {
  659. modifications.color = "#BE0";
  660. modifications.opacity = 0.5;
  661. }
  662. return modifications;
  663. };
  664. highlightLowAngles.getBackground = function() {
  665. return 'rgba(187,238,0,0.5)';
  666. };
  667.  
  668. /*
  669. *
  670. */
  671. var highlightExcessComponents = new WMEFunction("_cbHighlightHighExcessComponents", "Excess Components");
  672. highlightExcessComponents.getModifiedAttrs = function(wazeLineSegment) {
  673. var components = wazeLineSegment.geometry.components;
  674. if (components.length <= 2) {
  675. return new Object();
  676. }
  677. var foundIssue = false;
  678. var segmentProperties = getComponentsProperties(wazeLineSegment.geometry.components);
  679.  
  680. // If the space between components is really small, we note that as an issue
  681. var lengthSum = 0;
  682. for (var i = 0; i < segmentProperties.length; i++) {
  683. var componentLength = segmentProperties[i].distance;
  684. lengthSum += componentLength;
  685. }
  686. // if there is more than just a beginning and end component, and the difference from the total length is really small, this fits this category.
  687. var pStart = compToPoint(components[0]);
  688. var pEnd = compToPoint(components[components.length - 1]);
  689. var totalDist = getDistance(pStart, pEnd).distance;
  690. var lengthDiff = lengthSum - totalDist;
  691.  
  692. var numXtraComps = components.length - 2;
  693. // NEW
  694. var avgDiffPerSeg = lengthDiff / numXtraComps;
  695. var avgLengthPerSeg = lengthSum / numXtraComps;
  696. if (avgDiffPerSeg < 0.03) {
  697. foundIssue = true;
  698. } else if (avgLengthPerSeg < 3) {
  699. foundIssue = true;
  700. }
  701. var modifications = new Object();
  702. if (foundIssue) {
  703. modifications.color = "#FFD105";
  704. modifications.opacity = 0.5;
  705. }
  706. return modifications;
  707. };
  708. highlightExcessComponents.getBackground = function() {
  709. return 'rgba(255,209,5,0.5)';
  710. };
  711.  
  712. var highlightCloseComponents = new WMEFunction("_cbHighlightCloseComponents", "Close Components");
  713. highlightCloseComponents.getModifiedAttrs = function(wazeLineSegment) {
  714. var components = wazeLineSegment.geometry.components;
  715. if (components.length <= 2) { return }
  716. var segmentProperties = getComponentsProperties(wazeLineSegment.geometry.components);
  717.  
  718. // If the space between components is really small, we note that as an issue
  719. for (var i = 0; i < segmentProperties.length; i++) {
  720. var componentLength = segmentProperties[i].distance;
  721. if (componentLength < MIN_DISTANCE_BETWEEN_COMPONENTS) {
  722. return ERROR_MODS;
  723. }
  724. }
  725. };
  726. highlightCloseComponents.getBackground = function() {
  727. return ERROR_RGBA;
  728. };
  729.  
  730. var highlightZigZagsComponents = new WMEFunction("_cbHighlightZigZagsComponents", "Subtle Zig-Zags");
  731. highlightZigZagsComponents.getModifiedAttrs = function(wazeLineSegment) {
  732. var components = wazeLineSegment.geometry.components;
  733. if (components.length <= 2) {
  734. return new Object();
  735. }
  736. var foundIssue = false;
  737. var segmentProperties = getComponentsProperties(wazeLineSegment.geometry.components);
  738. var issueColor = "#E10";
  739.  
  740. if (subtleZigZags(segmentProperties)) {
  741. foundIssue = true;
  742. }
  743. var modifications = new Object();
  744. if (foundIssue) {
  745. modifications.color = issueColor;
  746. modifications.opacity = 0.5;
  747. }
  748. return modifications;
  749. };
  750. highlightZigZagsComponents.getBackground = function() {
  751. return 'rgba(238,16,0,0.5)';
  752. };
  753.  
  754.  
  755.  
  756. //
  757. // USER SELECTIONS DEFINITIONS FILE
  758. //
  759. var RoadTypeString = {
  760. 1 : "Streets",
  761. 2 : "Primary Street",
  762. 3 : "Freeways",
  763. 4 : "Ramps",
  764. 5 : "Walking Trails",
  765. 6 : "Major Highway",
  766. 7 : "Minor Highway",
  767. 8 : "Dirt roads",
  768. 10 : "Pedestrian Bw",
  769. 16 : "Stairway",
  770. 17 : "Private Road",
  771. 18 : "Railroad",
  772. 19 : "Runway/Taxiway",
  773. 20 : "Parking Lot Road",
  774. 21 : "Service Road"
  775. };
  776.  
  777. var speedColor = new WMEFunction("_cbHighlightSpeed", "Speed");
  778. var MAX_THRESHOLD_SPEED = 100;
  779. var MIN_WIDTH_SPEED = 4;
  780. var MAX_WIDTH_SPEED = 10;
  781. var MIN_OPACITY_SPEED = 0.4;
  782. var MAX_OPACITY_SPEED = 0.99;
  783.  
  784. speedColor.getModifiedAttrs = function(wazeLineSegment) {
  785. var modifications = new Object();
  786. var speedToUse = getSegmentSpeed(wazeLineSegment.segment);
  787. if (isNaN(speedToUse)) {
  788. speedToUse = 0;
  789. }
  790. var percentageWidth = Math.min(speedToUse, MAX_THRESHOLD_SPEED - 1) / MAX_THRESHOLD_SPEED;
  791. modifications.opacity = ((MAX_OPACITY_SPEED - MIN_OPACITY_SPEED) * percentageWidth) + MIN_OPACITY_SPEED;
  792. modifications.width = ((MAX_WIDTH_SPEED - MIN_WIDTH_SPEED) * percentageWidth) + MIN_WIDTH_SPEED;
  793. if (speedToUse < 1) {
  794. modifications.color = "#000";
  795. modifications.opacity = 0.2;
  796. } else {
  797. modifications.color = getScaledColour(speedToUse, 100);
  798. }
  799. return modifications;
  800. };
  801.  
  802. /*
  803. * HIGHLIGHT NO CITY
  804. */
  805. var highlightNoCity = new WMEFunction("_cbHighlightNoCity", "No City");
  806. highlightNoCity.getModifiedAttrs = function(wazeLineSegment) {
  807. var modifications = new Object();
  808. if (wazeLineSegment.noCity) {
  809. modifications.color = "#ff0";
  810. modifications.opacity = 0.3;
  811. }
  812. return modifications;
  813. };
  814. highlightNoCity.getBackground = function() {
  815. return 'rgba(255,255,0,0.3)';
  816. };
  817.  
  818. /*
  819. * highlight UNNAMED
  820. */
  821. var highlightNoName = new WMEFunction("_cbHighlightUnnamed", "Unnamed Street");
  822. highlightNoName.getModifiedAttrs = function(wazeLineSegment) {
  823. var modifications = new Object();
  824. if (wazeLineSegment.noName) {
  825. if (isTrafficRelevant(wazeLineSegment.attributes.roadType)) {
  826. modifications.color = "#424";
  827. modifications.opacity = 0.7;
  828. }
  829. }
  830. return modifications;
  831. };
  832. highlightNoName.getBackground = function() {
  833. return 'rgba(64,32,64,0.7)';
  834. };
  835.  
  836. /*
  837. * highlight HOUSE NUMBERS
  838. */
  839. var highlightHasHNs = new WMEFunction("_cbHighlightHNs", "Has House Numbers");
  840. highlightHasHNs.getModifiedAttrs = function(wazeLineSegment) {
  841. var modifications = new Object();
  842. if (wazeLineSegment.attributes.hasHNs) {
  843. modifications.color = "#0f0";
  844. modifications.opacity = 0.4;
  845. modifications.dasharray = "5 20";
  846. }
  847. return modifications;
  848. };
  849. highlightHasHNs.getBackground = function() {
  850. return 'rgba(0,255,0,0.4)';
  851. };
  852.  
  853. /*
  854. * highlight ALTERNATE NAME
  855. */
  856. var highlightWithAlternate = new WMEFunction("_cbHighlightWithAlternate", "With Alternate Name");
  857. highlightWithAlternate.getModifiedAttrs = function(wazeLineSegment) {
  858. var modifications = new Object();
  859. if (wazeLineSegment.secondaryStreetInfos.length > 0) {
  860. modifications.color = "#FFFF00";
  861. modifications.opacity = 0.7;
  862. }
  863. return modifications;
  864. };
  865. highlightWithAlternate.getBackground = function() {
  866. return 'rgba(256,256,0,0.7)';
  867. };
  868.  
  869. /*
  870. * highlight Extra Spaces in name
  871. */
  872. var highlightExtraSpaces = new WMEFunction("_cbhighlightExtraSpaces", "Extra Spaces");
  873. highlightExtraSpaces.getModifiedAttrs = function(wazeLineSegment) {
  874. if (wazeLineSegment.noName) { return }
  875. var streetName = wazeLineSegment.getStreetName();
  876. if(!streetName) { return }
  877. if(streetName.trim() != streetName || streetName.indexOf(" ") != -1) {
  878. var modifications = new Object();
  879. modifications.color = "#FF00FF";
  880. modifications.opacity = 0.7;
  881. return modifications;
  882. }
  883. };
  884. highlightExtraSpaces.getBackground = function() {
  885. return 'rgba(255,0,255,0.7)';
  886. };
  887.  
  888. /*
  889. * highlight Empty alternate street
  890. */
  891. var highlightEmptyAltStreetName = new WMEFunction("_cbighlightEmptyAltStreetName", "Empty alternate street");
  892. highlightEmptyAltStreetName.getModifiedAttrs = function(wazeLineSegment) {
  893. for(var strIDIndx = 0; strIDIndx < wazeLineSegment.secondaryStreetInfos.length; strIDIndx++) {
  894. if(wazeLineSegment.secondaryStreetInfos[strIDIndx].noName) {
  895. var modifications = new Object();
  896. modifications.color = "#FF00FF";
  897. modifications.opacity = 0.7;
  898. return modifications;
  899. }
  900. }
  901. };
  902. highlightEmptyAltStreetName.getBackground = function() {
  903. return 'rgba(255,0,255,0.7)';
  904. };
  905.  
  906. /*
  907. * highlight Invalid Abbreviations
  908. */
  909. var highlightInvalidAbbrevs = new WMEFunction("_cbhighlightInvalidAbbrev", "Invalid Abbreviations");
  910. highlightInvalidAbbrevs.getModifiedAttrs = function(wazeLineSegment) {
  911. if (wazeLineSegment.noName) { return }
  912. var streetName = wazeLineSegment.getStreetName();
  913. if(!streetName) { return }
  914. var idxOfPeriod = streetName.indexOf(".")
  915. if(idxOfPeriod != -1 && idxOfPeriod == streetName.length - 1) {
  916. var modifications = new Object();
  917. modifications.color = "#FF11AA";
  918. modifications.opacity = 0.7;
  919. return modifications;
  920. }
  921. };
  922. highlightInvalidAbbrevs.getBackground = function() {
  923. return 'rgba(255,17,170,0.7)';
  924. };
  925.  
  926. /*
  927. * highlight self connectivity
  928. */
  929. var highlightSelfConnectivity = new WMEFunction("_cbhighlightSelfConnectivity", "Self connectivity");
  930. highlightSelfConnectivity.getModifiedAttrs = function(wazeLineSegment) {
  931. if (wazeLineSegment.attributes.fromNodeID == wazeLineSegment.attributes.toNodeID) {
  932. return ERROR_MODS;
  933. }
  934. };
  935. highlightSelfConnectivity.getBackground = function() {
  936. return ERROR_RGBA;
  937. };
  938.  
  939. /*
  940. * highlight U-Turn at Dead End
  941. */
  942. var highlightUTurnAtEnd = new WMEFunction("_cbhighlightUTurnAtEnd", "U-Turn at dead end");
  943. highlightUTurnAtEnd.getModifiedAttrs = function(wazeLineSegment) {
  944. var toNodeDeadEndUturn = wazeLineSegment.ToNode.UTurnAllowed(wazeLineSegment.id) && wazeLineSegment.ToNode.isDeadEnd();
  945. var fromNodeDeadEndUturn = wazeLineSegment.FromNode.UTurnAllowed(wazeLineSegment.id) && wazeLineSegment.FromNode.isDeadEnd();
  946. if (toNodeDeadEndUturn || fromNodeDeadEndUturn) {
  947. var modifications = new Object();
  948. modifications.color = "#FF11AA";
  949. modifications.opacity = 0.7;
  950. return modifications;
  951. }
  952. };
  953. highlightUTurnAtEnd.getBackground = function() {
  954. return 'rgba(255,17,170,0.7)';
  955. };
  956.  
  957. /*
  958. * highlight three point segment
  959. */
  960. var highlightThreePointSegment = new WMEFunction("_cbhighlightThreePointSegment", "Three Point Segment");
  961. highlightThreePointSegment.getModifiedAttrs = function(wazeLineSegment) {
  962. var modifications = new Object();
  963. var toNodeSegIDs = wazeLineSegment.ToNode.attributes.segIDs;
  964. var fromNodeSegIDs = wazeLineSegment.FromNode.attributes.segIDs;
  965. var commonNodesFromTo = (toNodeSegIDs.filter(function(n) { return n != wazeLineSegment.id && fromNodeSegIDs.indexOf(n) != -1 }))
  966. var commonNodesFromFrom = (fromNodeSegIDs.filter(function(n) { return n != wazeLineSegment.id && toNodeSegIDs.indexOf(n) != -1 }))
  967. var commonSegment = commonNodesFromTo.length > 0 || commonNodesFromFrom.length > 0;
  968. if(commonSegment) {
  969. modifications.color = "#FF11AA";
  970. modifications.opacity = 0.7;
  971. }
  972.  
  973. return modifications;
  974. };
  975. highlightThreePointSegment.getBackground = function() {
  976. return 'rgba(255,17,170,0.7)';
  977. };
  978.  
  979. /*
  980. * highlight CONST ZN
  981. */
  982. var highlightConstZn = new WMEFunction("_cbHighlightConstZn", "CONST ZN Street");
  983. highlightConstZn.getModifiedAttrs = function(wazeLineSegment) {
  984. var modifications = new Object();
  985.  
  986. if (!wazeLineSegment.noName && wazeLineSegment.getStreetName().indexOf('CONST ZN') != -1) {
  987. modifications.color = "#FF6600";
  988. modifications.dasharray = "2 15";
  989. modifications.opacity = 0.7;
  990. }
  991. return modifications;
  992. };
  993. highlightConstZn.getBackground = function() {
  994. return 'rgba(255,102,0,0.7)';
  995. };
  996.  
  997. function getCurrentHoverSegment() {
  998. return highlightSegmentMonitor.getLatestSegment();
  999. }
  1000.  
  1001. /*
  1002. * highlight SAME NAME
  1003. */
  1004. var highlightSameName = new WMEFunction("_cbHighlightSameName", "Same Street Name");
  1005. highlightSameName.getModifiedAttrs = function(wazeLineSegment) {
  1006. var modifications = new Object();
  1007. var segment = getCurrentHoverSegment();
  1008. if (segment != null) {
  1009. var highlightedStreetID = segment.attributes.primaryStreetID;
  1010. if (wazeLineSegment.attributes.primaryStreetID === highlightedStreetID) {
  1011. if (wazeLineSegment.segment.fid !== segment.fid) {
  1012. modifications.dasharray = "5 15";
  1013. }
  1014. modifications.color = "#0ad";
  1015. modifications.opacity = 0.5;
  1016. }
  1017. }
  1018. return modifications;
  1019. };
  1020. highlightSameName.getBackground = function() {
  1021. return 'rgba(0,160,208,0.5)';
  1022. };
  1023.  
  1024. /*
  1025. * highlight TOLL
  1026. */
  1027. var highlightToll = new WMEFunction("_cbHighlightToll", "Toll");
  1028. highlightToll.getModifiedAttrs = function(wazeLineSegment) {
  1029. var modifications = new Object();
  1030. if (wazeLineSegment.attributes.fwdToll) {
  1031. modifications.color = wazeLineSegment.attributes.locked ? "#ff0000" : "#00f";
  1032. modifications.opacity = 0.5;
  1033. modifications.dasharray = "5 15";
  1034. }
  1035. return modifications;
  1036. };
  1037. highlightToll.getBackground = function() {
  1038. return 'rgba(0,0,255,0.5)';
  1039. };
  1040.  
  1041. /*
  1042. * highlight NO DIRECTION
  1043. */
  1044. var highlightNoDirection = new WMEFunction("_cbHighlightNoDirection", "Unknown Direction");
  1045. highlightNoDirection.getModifiedAttrs = function(wazeLineSegment) {
  1046. var modifications = new Object();
  1047. if (wazeLineSegment.noDirection) {
  1048. modifications.color = "#100";
  1049. modifications.opacity = 0.8;
  1050. }
  1051. return modifications;
  1052. };
  1053. highlightNoDirection.getBackground = function() {
  1054. return 'rgba(10,0,0,0.8)';
  1055. };
  1056.  
  1057. /*
  1058. * highlight ONE WAY
  1059. */
  1060. var highlightOneWay = new WMEFunction("_cbHighlightOneWay", "One Way");
  1061. highlightOneWay.getModifiedAttrs = function(wazeLineSegment) {
  1062. var modifications = new Object();
  1063. if (wazeLineSegment.oneWay) {
  1064. modifications.color = "#00f";
  1065. modifications.opacity = 0.2;
  1066. }
  1067. return modifications;
  1068. };
  1069. highlightOneWay.getBackground = function() {
  1070. return 'rgba(0,0,255,0.2)';
  1071. };
  1072. highlightOneWay.getDetail = function(segment) {
  1073. return isOneWay(segment);
  1074. };
  1075.  
  1076. /*
  1077. * highlight NON A->B ONE WAY
  1078. */
  1079. var highlightNonABOneWay = new WMEFunction("_cbHighlightNonABOneWay", "Non A&rarr;B One Way");
  1080. highlightNonABOneWay.getModifiedAttrs = function(wazeLineSegment) {
  1081. var modifications = new Object();
  1082. if (wazeLineSegment.oneWay && wazeLineSegment.attributes.revDirection) {
  1083. modifications.color = "#a00";
  1084. modifications.opacity = 0.5;
  1085. }
  1086. return modifications;
  1087. };
  1088. highlightNonABOneWay.getBackground = function() {
  1089. return 'rgba(160,0,0.5)';
  1090. };
  1091.  
  1092.  
  1093. /*
  1094. * highlight UNTERMINATED
  1095. */
  1096.  
  1097. var highlightNoTerm = new WMEFunction("_cbHighlightNoTerm", "Unterminated");
  1098. highlightNoTerm.getModifiedAttrs = function(wazeLineSegment) {
  1099. var modifications = new Object();
  1100. if (wazeLineSegment.attributes.toNodeID == null || wazeLineSegment.attributes.fromNodeID == null) {
  1101. modifications.color = "#FC0";
  1102. modifications.opacity = 0.7;
  1103. }
  1104. return modifications;
  1105. };
  1106. highlightNoTerm.getBackground = function() {
  1107. return 'rgba(255,208,0,0.7)';
  1108. };
  1109.  
  1110. var highlightEditor = new WMEFunctionExtended("_cbHighlightEditor", "Specific Editor");
  1111. highlightEditor.getModifiedAttrs = function(wazeLineSegment) {
  1112. var selectUser = getId(highlightEditor.getSelectId());
  1113. var selectedUserId = selectUser.options[selectUser.selectedIndex].value;
  1114. var updatedBy = wazeLineSegment.attributes.updatedBy;
  1115.  
  1116. var modifications = new Object();
  1117. if (updatedBy == selectedUserId) {
  1118. modifications.color = "#00ff00";
  1119. modifications.opacity = 0.5;
  1120. }
  1121. return modifications;
  1122. };
  1123. highlightEditor.buildExtended = function() {
  1124. return '<select id="' + this.getSelectId() + '" name="' + this.getSelectId() + '"><br />';
  1125. }
  1126. highlightEditor.init = function() {
  1127. getId(this.getCheckboxId()).onclick = highlightSegments;
  1128. getId(this.getSelectId()).onchange = this.getSelectFieldChangeFunction();
  1129. }
  1130. highlightEditor.getBackground = function() {
  1131. return 'rgba(0,255,0,0.5)';
  1132. };
  1133.  
  1134. /*
  1135. * RECENTLY Edited
  1136. */
  1137. var highlightRecent = new WMEFunctionExtended("_cbHighlightRecent", "Recently Edited");
  1138. highlightRecent.getModifiedAttrs = function(wazeLineSegment) {
  1139. var numDays = getId(this.getSelectId()).value;
  1140. if (numDays == undefined) {
  1141. numDays = 0;
  1142. }
  1143. var tNow = new Date();
  1144. var tDif = (tNow.getTime() - wazeLineSegment.updatedOn.getTime()) / 86400000;
  1145. var modifications = new Object();
  1146.  
  1147. if (numDays >= 0 && tDif <= numDays) {
  1148. var heatScale = 0.75 / numDays;
  1149. modifications.color = "#0f0";
  1150. modifications.opacity = Math.min(0.999999, 1 - (tDif * heatScale));
  1151. }
  1152. return modifications;
  1153. };
  1154. highlightRecent.buildExtended = function() {
  1155. return '<input type="number" min="0" max="365" size="3" value="7" id="' + this.getSelectId() + '" /> days';
  1156. }
  1157. highlightRecent.init = function() {
  1158. getId(this.getCheckboxId()).onclick = highlightSegments;
  1159. getId(this.getSelectId()).onfocus = populateUserList;
  1160. getId(this.getSelectId()).onchange = highlightSegments;
  1161. };
  1162. highlightRecent.getBackground = function() {
  1163. return 'rgba(0,255,0,0.7)';
  1164. };
  1165.  
  1166. /*
  1167. * LOCKED segments
  1168. */
  1169. var highlightLocked = new WMEFunctionExtended("_cbHighlightLocked", "Locked");
  1170. highlightLocked.getModifiedAttrs = function(wazeLineSegment) {
  1171. var modifications = new Object();
  1172. if (wazeLineSegment.attributes.locked) {
  1173. modifications.color = "#B00";
  1174. modifications.opacity = 0.8;
  1175. }
  1176. return modifications;
  1177. };
  1178. highlightLocked.getBackground = function() {
  1179. return 'rgba(176,0,0,0.8)';
  1180. };
  1181.  
  1182. /*
  1183. * highlight RESTRICTIONS
  1184. */
  1185. var highlightSegmentRestrictions = new WMEFunction("_cbhighlightSegmentRestrictions", "Segment Restrictions");
  1186. highlightSegmentRestrictions.getModifiedAttrs = function(wazeLineSegment) {
  1187. var modifications = new Object();
  1188. if (hasRestrictions(wazeLineSegment.attributes)) {
  1189. modifications.color = "#FAFF00";
  1190. modifications.dasharray = "2 15";
  1191. modifications.opacity = 0.8;
  1192. }
  1193. return modifications;
  1194. };
  1195. highlightSegmentRestrictions.getBackground = function() {
  1196. return 'rgba(250,255,0,0.8)';
  1197. };
  1198.  
  1199. /*
  1200. * highlight ROAD TYPE
  1201. */
  1202. var highlightRoadType = new WMEFunctionExtended("_cbHighlightRoadType", "Road Type");
  1203. highlightRoadType.roadTypeStrings = RoadTypeString;
  1204. highlightRoadType.getModifiedAttrs = function(wazeLineSegment) {
  1205.  
  1206. var currentRoadTypeElement = getId(this.getSelectId());
  1207. var currentRoadType = currentRoadTypeElement.options[currentRoadTypeElement.selectedIndex].value;
  1208. if (currentRoadType == undefined) {
  1209. currentRoadType = 0;
  1210. }
  1211.  
  1212. var modifications = new Object();
  1213. if (currentRoadType == wazeLineSegment.attributes.roadType) {
  1214. modifications.color = "#0f0";
  1215. modifications.opacity = 0.5;
  1216. }
  1217. return modifications;
  1218. };
  1219. highlightRoadType.buildExtended = function() {
  1220. return '<select id="' + this.getSelectId() + '" name="' + this.getSelectId() + '">';
  1221. }
  1222. highlightRoadType.init = function() {
  1223. populateOption(this.getSelectId(), this.roadTypeStrings);
  1224. getId(this.getCheckboxId()).onclick = highlightSegments;
  1225. getId(this.getSelectId()).onchange = this.getSelectFieldChangeFunction();
  1226. };
  1227. highlightRoadType.getBackground = function() {
  1228. return 'rgba(0,255,0,0.5)';
  1229. };
  1230.  
  1231. /*
  1232. * highlight City
  1233. */
  1234. var highlightCity = new WMEFunctionExtended("_cbHighlightCity", "City");
  1235. highlightCity.getModifiedAttrs = function(wazeLineSegment) {
  1236.  
  1237. var currentCityElement = getId(this.getSelectId());
  1238. var currentCity = currentCityElement.options[currentCityElement.selectedIndex].value;
  1239. if (currentCity == undefined) {
  1240. currentCity = 0;
  1241. }
  1242.  
  1243. var modifications = new Object();
  1244. if (currentCity == wazeLineSegment.cityID) {
  1245. modifications.color = "#0f0";
  1246. modifications.opacity = 0.5;
  1247. } else if (currentCity == WME_SPEED_UNKNOWN && wazeLineSegment.noCity) {
  1248. modifications.color = "#0f0";
  1249. modifications.opacity = 0.5;
  1250. }
  1251. return modifications;
  1252. };
  1253. highlightCity.buildExtended = function() {
  1254. return '<select id="' + this.getSelectId() + '" name="' + this.getSelectId() + '">';
  1255. }
  1256. highlightCity.init = function() {
  1257. getId(this.getCheckboxId()).onclick = highlightSegments;
  1258. getId(this.getSelectId()).onchange = this.getSelectFieldChangeFunction();
  1259. };
  1260. highlightCity.getBackground = function() {
  1261. return 'rgba(0,255,0,0.5)';
  1262. };
  1263. highlightCity.getDetail = function(segment) {
  1264. return;
  1265. };
  1266.  
  1267. /*
  1268. * highlight Street
  1269. */
  1270. var highlightStreet = new WMEFunctionExtended("_cbHighlightStreet", "Street");
  1271. highlightStreet.getModifiedAttrs = function(wazeLineSegment) {
  1272.  
  1273. var currentCityElement = getId(this.getSelectId());
  1274. var currentCity = currentCityElement.options[currentCityElement.selectedIndex].value;
  1275. if (currentCity == undefined) {
  1276. currentCity = 0;
  1277. }
  1278.  
  1279. var modifications = new Object();
  1280. if (currentCity == wazeLineSegment.cityID) {
  1281. modifications.color = "#0f0";
  1282. modifications.opacity = 0.5;
  1283. } else if (currentCity == WME_SPEED_UNKNOWN && wazeLineSegment.noCity) {
  1284. modifications.color = "#0f0";
  1285. modifications.opacity = 0.5;
  1286. }
  1287. return modifications;
  1288. };
  1289. highlightStreet.buildExtended = function() {
  1290. return '<select id="' + this.getSelectId() + '" name="' + this.getSelectId() + '">';
  1291. }
  1292. highlightStreet.init = function() {
  1293. getId(this.getCheckboxId()).onclick = highlightSegments;
  1294. getId(this.getSelectId()).onchange = this.getSelectFieldChangeFunction();
  1295. };
  1296. highlightStreet.getBackground = function() {
  1297. return 'rgba(0,255,0,0.5)';
  1298. };
  1299.  
  1300. /*
  1301. * highlight Short Segments
  1302. */
  1303. var highlightShortSegments = new WMEFunctionExtended("_cbHighlightShortSegments", "Short");
  1304. highlightShortSegments.getModifiedAttrs = function(wazeLineSegment) {
  1305. var length = getId(this.getSelectId()).value;
  1306. if (length == undefined) {
  1307. length = 0;
  1308. }
  1309.  
  1310. var modifications = new Object();
  1311. if (wazeLineSegment.attributes.length < length) {
  1312. modifications.color = "#f33";
  1313. modifications.opacity = 0.8;
  1314. modifications.width = 15;
  1315. }
  1316. return modifications;
  1317. };
  1318. highlightShortSegments.buildExtended = function() {
  1319. return '<input type="number" min="0" max="100" value="5" size="3" id="' + this.getSelectId() + '" /> meters';
  1320. }
  1321. highlightShortSegments.init = function() {
  1322. getId(this.getCheckboxId()).onclick = highlightSegments;
  1323. getId(this.getSelectId()).onchange = highlightSegments;
  1324. getId(this.getSelectId()).onchange = highlightSegments;
  1325. };
  1326. highlightShortSegments.getBackground = function() {
  1327. return 'rgba(255,51,51,0.8)';
  1328. };
  1329.  
  1330. /*
  1331. * highlight NULL
  1332. */
  1333. var highlightNull = new WMEFunction("_cbHighlightNull", "NULL");
  1334. highlightNull.getModifiedAttrs = function(wazeLineSegment) {
  1335. var modifications = new Object();
  1336. modifications.color = "#dd7700";
  1337. modifications.opacity = 0.001;
  1338. modifications.dasharray = "none";
  1339. modifications.width = 8;
  1340. return modifications;
  1341. };
  1342.  
  1343. /* *************************************************** */
  1344.  
  1345. /*
  1346. * Sections of highlighters
  1347. */
  1348. var highlightSection = new SelectSection("Highlight Segments", 'WME_Segments_section', [highlightOneWay, highlightToll, highlightNoName, highlightWithAlternate, highlightCity, highlightRoadType, highlightSameName, highlightConstZn, highlightSegmentRestrictions]);
  1349. // Disabled:
  1350. // ----------------
  1351. // speedColor
  1352.  
  1353.  
  1354. var geometrySection = new SelectSection("Geometry", 'WME_geometry_section', [highlightExcessComponents, highlightLowAngles, highlightZigZagsComponents, highlightCloseComponents, highlightNoTerm, highlightShortSegments]);
  1355. var issuesSection = new SelectSection("Potential Issues", 'WME_issues_section', [highlightSelfConnectivity, highlightExtraSpaces, highlightEmptyAltStreetName, highlightInvalidAbbrevs, highlightNoDirection, highlightThreePointSegment]);
  1356. // Disabled:
  1357. // ----------------
  1358. // highlightUTurnAtEnd
  1359.  
  1360. var advancedSection = new SelectSection("Advanced", 'WME_Advanced_section', [highlightEditor, highlightRecent, highlightLocked, highlightNonABOneWay, highlightHasHNs]);
  1361.  
  1362. var selectSections = [highlightSection, issuesSection, geometrySection, advancedSection];
  1363.  
  1364. var allModifiers = [];
  1365. /** The list of all modifiers to display **/
  1366. for (var i = 0; i < selectSections.length; i++) {
  1367. allModifiers = allModifiers.concat(selectSections[i].selections);
  1368. }
  1369.  
  1370. var hoverDependentSections = [highlightSameName];
  1371. // var allModifiers = [geometrySection.selections, highlightSection.selections, advancedSection.selections];
  1372. //
  1373. // POPUP DIALOG
  1374. //
  1375. var WME_SPEED_Popup = document.createElement('div');
  1376. WME_SPEED_Popup.id = 'WME_SPEED_Popup';
  1377. getId('editor-container').appendChild(WME_SPEED_Popup);
  1378.  
  1379. function getDirectionalSection(segment, isFreeway) {
  1380. var userString = "";
  1381. // Add "One Way" arrow
  1382. if(!isFreeway && isOneWay(segment)) {
  1383. userString += "<div style='background: #000; color:#fff;font-size:.92em;font-weight:bold;line-height:.7em;'>"
  1384. userString += "<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAARCAAAAAC6bKD1AAABp0lEQVR4XpXRX0hTcRyH4dfDZDW0CSPWqoVnEQghXfQHodNVXYaRYGAXFVjkRRTBumgjCJMZWkMLgnkRWWIorYZhrVKSwv5ehLnFcSw4DaE11s1ghcnhF4yzc+487Ll/4cvnSyHzfLoGL7K/UXdgwztyBEtrhqfYaRdiYhOmV5KOnflVjqVOYHIAbF7PWtRWPKNdPT8wJIA5IRbiZTEn/n7Uksl3QuS/Lau5rFj8mdJE+bWoKJ2TjMOoeN+ZOMrhZCH4uPfRLCz13rp0b4auwVLH6rUZKhpvv2kBwEjGIveLy86QDh3RMMja289ZOS1N7dt9PhHCsP9LuN5K8s0055v2jsKNtjL4tF87X8qTBz0f+icHXFSt63tYZybeHDkvV2MQTjeAo3HPgeLWuFo34Qm0YdKHTgozOR46s8GPrwfiFy4DsqL4ljY+S07rWNLKxXJ1ZFDGMlFiBA/5tlMP9PsbHjTdwX135aabCv5dj6xYfznlAvqoCmIwjO8CPp1eBCvRWIu7Bf5cGdapJhJ2FCezZ79jSW3BxrYn3RKmgEphYaomX4v/Ae4Q1fDFrZZBAAAAAElFTkSuQmCC' />"
  1385. userString += "</div>"
  1386. }
  1387. // Add "No Entrance" hint
  1388. else if(isNoDirection(segment)) {
  1389. userString += "<div style='max-height:17px;height:17px; background-color:#C00000;padding:0;border:0;'>"
  1390. userString += "<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD8AAAARCAMAAABdJ4SrAAAAVFBMVEXAAAD////JJCTjjY3yycnLLS389fXNNTXEERHJJibooqLhh4fww8PVVFTHHR3XXl7VV1fTTEzxxsbLKyvrrKzGGhr9+fnjjIzggYHRRUXjjo7QPz/hgZD7AAAAS0lEQVR4Xt3LtwHAMAwDMMnpvff//8zKlfRm7LA0VIFVjNDr0mkd/MZ5LfxH+D38Qfg5/Cnyz5F/Ef4KfxP+Dv84+X8ZuDPW+1kKfk1aBDuOnLwdAAAAAElFTkSuQmCC' style='margin:0; padding:0; border:0;' />"
  1391. userString += "</div>"
  1392. }
  1393. return userString;
  1394. }
  1395. function showProps(obj, objName) {
  1396. var result = "";
  1397. for (var i in obj) {
  1398. if (obj.hasOwnProperty(i)) {
  1399. result += objName + "." + i + " = " + obj[i] + "\n";
  1400. }
  1401. }
  1402. return result;
  1403. }
  1404.  
  1405. function getPropsHTML(segment, matchingActions, namingMap, otherItemsMap) {
  1406. matchingActions = typeof matchingActions !== 'undefined' ? matchingActions : {};
  1407. namingMap = typeof namingMap !== 'undefined' ? namingMap : {};
  1408. otherItemsMap = typeof otherItemsMap !== 'undefined' ? otherItemsMap : {};
  1409. var userString = ""
  1410. if(true) {
  1411. userString += "<div id='segment_details' style='font-size: 0.6em'>"
  1412. if(false) {
  1413. userString += "hasEmptyStreet: " + segment.hasEmptyStreet() + "<br />"
  1414. var segAddress = segment.getAddress();
  1415. userString += "getAddress: " + segAddress + "<br />"
  1416. for (var addritem in segAddress) {
  1417. userString += "addr item: " + addritem + "<br />"
  1418. }
  1419. var segAddressDetails = segment.getAddressDetails();
  1420. userString += "getAddressDetails: " + segAddressDetails + "<br />"
  1421. for (var addritemDetail in segAddressDetails) {
  1422. userString += "addr item detail: " + addritemDetail + "<br />"
  1423. }
  1424. }
  1425. if(true) {
  1426. // userString += "getRevHeading: " + segment.getRevHeading() + "<br />"
  1427. // userString += "getFwdHeading: " + segment.getFwdHeading() + "<br />"
  1428. for(var keyname in segment.attributes) {
  1429. var keyNameString = namingMap[keyname] ? namingMap[keyname] : keyname;
  1430. var action = matchingActions[keyname];
  1431. if(action) {
  1432. var actionResult = action(segment.attributes)
  1433. if(actionResult) {
  1434. userString += keyNameString + ": " + actionResult + "<br />"
  1435. }
  1436. } else {
  1437. var value = segment.attributes[keyname];
  1438. if(value != null) {
  1439. userString += keyNameString + ": " + value + "<br />"
  1440. }
  1441. }
  1442. }
  1443. for(var otherName in otherItemsMap) {
  1444. var action = otherItemsMap[otherName];
  1445. if(action) {
  1446. var actionResult = action(segment)
  1447. if(actionResult) {
  1448. userString += otherName + ": " + actionResult + "<br />"
  1449. }
  1450. }
  1451. }
  1452. }
  1453. userString += "</div>"
  1454. }
  1455. return userString;
  1456. }
  1457. function showPopup(segment) {
  1458. var user = Waze.loginManager.getLoggedInUser();
  1459. // var segment = getCurrentHoverSegment();
  1460. if(segment != null && segment.CLASS_NAME == "Waze.Feature.Vector.Segment") {
  1461. // console.log(showProps(segment, "segment"));
  1462. // console.log(showProps(segment.attributes, "segment.attributes"));
  1463. // var cmpnnts = segment.geometry.components;
  1464. // var compSegs = getComponentsProperties(cmpnnts);
  1465. var popupClass = "";
  1466. if(segment.attributes.lockRank > 0) {
  1467. if(segment.attributes.lockRank > user.rank) {
  1468. popupClass += "userlocked";
  1469. }
  1470. else {
  1471. popupClass += "locked";
  1472. }
  1473. }
  1474. var userString = "<div id='popup_container' class='" + popupClass + "'>";
  1475. var sid = segment.attributes.primaryStreetID;
  1476. var street = Waze.model.streets.get(sid);
  1477. if(typeof street != 'undefined') {
  1478. var isFreeway = false;
  1479. var streetStyleClass = 'WME_SPEED_streetSign';
  1480. switch(segment.attributes.roadType) {
  1481. case 3 : //freeway
  1482. isFreeway = true;
  1483. break;
  1484. case 17: // Private Road
  1485. streetStyleClass = 'WME_SPEED_privateStreet';
  1486. break;
  1487. case 20: // Parking Lot Road
  1488. streetStyleClass = 'WME_SPEED_parkingLot';
  1489. break;
  1490. case 5: //Walking Trails
  1491. case 10: //Pedestrian Bw
  1492. streetStyleClass = 'WME_SPEED_trailSign';
  1493. break;
  1494. case 8: // Dirt Road
  1495. streetStyleClass = 'WME_SPEED_dirtRoadSign';
  1496. break;
  1497. case 18: // Railroad
  1498. streetStyleClass = 'WME_SPEED_railroadSign';
  1499. break;
  1500. default:
  1501. break;
  1502. }
  1503. if(sid) {
  1504. var streetName = street.name;
  1505. if(streetName == null || streetName == "") {
  1506. streetName = '[UNKNOWN]';
  1507. streetStyleClass += " WME_SPEED_unknownName";
  1508. }
  1509. var alternateSection = "";
  1510. if(segment.attributes.streetIDs && segment.attributes.streetIDs.length > 0) {
  1511. alternateSection += "<div class='WME_SPEED_alternateName'>";
  1512. for(var i = 0; i < segment.attributes.streetIDs.length; i++) {
  1513. var altStreet = Waze.model.streets.get(segment.attributes.streetIDs[i]);
  1514. alternateSection += '<div class="' + streetStyleClass + '">' + altStreet.name + '</div>';
  1515. }
  1516. alternateSection += "</div>";
  1517. }
  1518. var isInterstate = false;
  1519. if(isFreeway) { // freeway
  1520. var regexMatch = streetName.match(InterstateRegEx);
  1521. if(regexMatch != null) {
  1522. isInterstate = true;
  1523. streetStyleClass = 'WME_SPEED_interstate';
  1524. var interstateNum = regexMatch.first().substr(2).trim();
  1525. streetName = interstateNum;
  1526. }
  1527. }
  1528. // Add "Toll"
  1529. if(segment.attributes.revToll || segment.attributes.fwdToll) {
  1530. userString += "<div id='WME_SPEED_tollRoad'>Toll</div>"
  1531. }
  1532. userString += getDirectionalSection(segment, isFreeway);
  1533.  
  1534. userString += "<div id='popup_street_name' class='" + streetStyleClass + "'>";
  1535. var streetNamePieces = streetName.split('/');
  1536. for(var snpIndex = 0; snpIndex < streetNamePieces.length; snpIndex++) {
  1537. var prefixStr = "";
  1538. var suffixStr = "";
  1539. var steetNamePiece = streetNamePieces[snpIndex].trim();
  1540. for(var i = 0; i < FRONT_ABBREVS.length; i++) {
  1541. var strToMatch = FRONT_ABBREVS[i] + " ";
  1542. var startIndex = steetNamePiece.search(strToMatch)
  1543. if(startIndex == 0) {
  1544. prefixStr = "<span id='street_name_prefix'>" + steetNamePiece.slice(startIndex,strToMatch.length) + "</span>";
  1545. steetNamePiece = steetNamePiece.slice(strToMatch.length);
  1546. break;
  1547. }
  1548. }
  1549. for(var i = 0; i < END_ABBREVS.length; i++) {
  1550. var strToMatch = " " + END_ABBREVS[i];
  1551. var expectedIndex = steetNamePiece.length - strToMatch.length;
  1552. if(expectedIndex > 0 && steetNamePiece.search(strToMatch) == expectedIndex) {
  1553. suffixStr = "<span id='street_name_suffix'>" + steetNamePiece.slice(expectedIndex) + "</span>";
  1554. steetNamePiece = steetNamePiece.slice(0, expectedIndex);
  1555. break;
  1556. }
  1557. }
  1558. userString += prefixStr + steetNamePiece + suffixStr;
  1559. if(snpIndex != streetNamePieces.length - 1) {
  1560. userString += '<br />';
  1561. }
  1562. }
  1563. userString += "</div>";
  1564. }
  1565. var city = Waze.model.cities.get(street.cityID);
  1566. if(city && city.name) {
  1567. userString += "<div id='popup_street_city' class='" + streetStyleClass + "'>"
  1568. userString += city.name;
  1569. userString += "</div>"
  1570. }
  1571. userString += alternateSection;
  1572. }
  1573. var speedToUse = getSegmentSpeed(segment);
  1574. if(!isNaN(speedToUse) || typeof speedToUse === "string") {
  1575. userString += "<div id='popup_speed'>"
  1576. userString += "<div id='popup_speed_header'>SPEED<br />LIMIT</div><div id='popup_speed_value'>" + speedToUse + "</div>"
  1577. userString += "</div>";
  1578. }
  1579. // roadTypeToString
  1580. userString += getPropsHTML(segment,
  1581. {
  1582. 'createdOn': function(segmentAttr) {
  1583. var dateVal = new Date(segmentAttr.createdOn)
  1584. return dateToDateString(dateVal);
  1585. },
  1586. 'updatedOn': function(segmentAttr) {
  1587. var dateVal = new Date(segmentAttr.updatedOn)
  1588. return dateToDateString(dateVal);
  1589. },
  1590. 'roadType' : function(segmentAttr) { return roadTypeToString(segmentAttr.roadType); },
  1591. 'length' : function(segmentAttr) { return lengthToString(segmentAttr.length); },
  1592. 'fwdRestrictions' : function(segmentAttr) { return hasRestrictions(segmentAttr) ? "Yes" : undefined },
  1593. 'revRestrictions' : function(segmentAttr) {},
  1594. 'version' : function(segmentAttr) {},
  1595. 'separator' : function(segmentAttr) {},
  1596. 'fromNodeID' : function(segmentAttr) {},
  1597. 'toNodeID' : function(segmentAttr) {},
  1598. 'level' : function(segmentAttr) {},
  1599. 'validated' : function(segmentAttr) {},
  1600. 'createdBy' : function(segmentAttr) {},
  1601. 'updatedBy' : function(segmentAttr) {},
  1602. 'primaryStreetID' : function(segmentAttr) {},
  1603. 'streetIDs' : function(segmentAttr) {},
  1604. 'permissions' : function(segmentAttr) {},
  1605. 'fwdTurnsLocked' : function(segmentAttr) {},
  1606. 'revTurnsLocked' : function(segmentAttr) {},
  1607. 'fwdToll' : function(segmentAttr) { return undefined },
  1608. 'revToll' : function(segmentAttr) {},
  1609. 'allowNoDirection' : function(segmentAttr) {},
  1610. 'lockRank' : function(segmentAttr) {},
  1611. 'rank' : function(segmentAttr) {},
  1612. 'type' : function(segmentAttr) {},
  1613. 'fwdDirection' : function(segmentAttr) {},
  1614. 'revDirection' : function(segmentAttr) {},
  1615. }, {'hasHNs' : "Has House Numbers",
  1616. 'roadType' : "Road Type",
  1617. 'fwdRestrictions' : "Restrictions",
  1618. 'fwdToll' : "Toll Road" }, {
  1619. "Segments" : function(segmnt) { return segmnt.geometry.components.length}
  1620. });
  1621.  
  1622. var checkedMods = checkedModifiers()
  1623. for(var i = 0; i < checkedMods.length; i++) {
  1624. var checkedVal = checkedMods[i].getDetail(segment);
  1625. if(typeof checkedVal != 'undefined') {
  1626. userString += checkedMods[i].text + ': ' + checkedVal + '<br />';
  1627. }
  1628. }
  1629. userString += "</div>"
  1630.  
  1631. WME_SPEED_Popup.innerHTML = userString;
  1632. }
  1633. else {
  1634. WME_SPEED_Popup.innerHTML = "";
  1635. }
  1636. }//
  1637. // CORE FILE
  1638. //
  1639.  
  1640. var DEBUG = true;
  1641. function debug(message) {
  1642. if(DEBUG) {
  1643. console.log(message);
  1644. }
  1645. }
  1646.  
  1647. var possibleWazeMapEvents = ["mouseout", "zoomend"];
  1648. var possibleControllerEvents = ["loadend"];
  1649. var possiblePendingControllerEvents = [];
  1650. var possibleSelectionModifyEvents = ["deactivate", "featuredeselected"];
  1651. var possibleSelectionEvents = ["selectionchanged"];
  1652. var possibleSelectionModifyHoverEvents = [];
  1653. var possibleActionEvents = [];
  1654.  
  1655.  
  1656. var webStorageSupported = ('localStorage' in window) && window['localStorage'] !== null;
  1657.  
  1658. function checkedModifiers() {
  1659. var checkedModifiers = [];
  1660. for (var i = 0; i < allModifiers.length; i++) {
  1661. var segModGroup = allModifiers[i];
  1662. var isChecked = getId(segModGroup.getCheckboxId()).checked
  1663. if (isChecked) {
  1664. checkedModifiers[checkedModifiers.length] = segModGroup;
  1665. }
  1666. }
  1667. return checkedModifiers;
  1668. }
  1669.  
  1670. function highlightAllSegments() {
  1671. modifySegements(highlightNull);
  1672. highlightSegments(allModifiers);
  1673. }
  1674.  
  1675. function highlightSegments(modifiers) {
  1676. if(!modifiers) {
  1677. modifiers = allModifiers;
  1678. }
  1679. for (var i = 0; i < modifiers.length; i++) {
  1680. var segModGroup = modifiers[i];
  1681. var isChecked = getId(segModGroup.getCheckboxId()).checked
  1682. if (isChecked) {
  1683. modifySegements(segModGroup);
  1684. }
  1685. if(webStorageSupported) {
  1686. if(isChecked) {
  1687. window.localStorage.setItem(segModGroup.checkboxId, 'checked');
  1688. } else {
  1689. window.localStorage.removeItem(segModGroup.checkboxId);
  1690. }
  1691. }
  1692. }
  1693. return true;
  1694. }
  1695.  
  1696. function enumerateAllModifiers(work) {
  1697. for (var i = 0; i < allModifiers.length; i++) {
  1698. var segModGroup = allModifiers[i];
  1699. work(segModGroup);
  1700. }
  1701. }
  1702.  
  1703. function modifySegements(modifier) {
  1704. for (var seg in Waze.model.segments.objects) {
  1705. var segment = Waze.model.segments.get(seg);
  1706. var attributes = segment.attributes;
  1707. var line = getId(segment.geometry.id);
  1708.  
  1709. if (line != null) {
  1710. var sid = attributes.primaryStreetID;
  1711. if (sid == null)
  1712. continue;
  1713. if(Waze.model.streets.get(sid) == null) {
  1714. continue;
  1715. }
  1716. var currentColor = line.getAttribute("stroke");
  1717. var currentOpacity = line.getAttribute("stroke-opacity");
  1718. var currentDashes = line.getAttribute("stroke-dasharray");
  1719. var currentWidth = line.getAttribute("stroke-width");
  1720.  
  1721. // check that WME hasn't highlighted this segment
  1722. if (currentOpacity == 1 || currentWidth == 9) {
  1723. continue;
  1724. }
  1725.  
  1726. var roadType = attributes.roadType;
  1727. if (Waze.map.zoom <= 3 && (roadType < 2 || roadType > 7)) {
  1728. if (currentOpacity > 0.1) {
  1729. line.setAttribute("stroke", "#dd7700");
  1730. line.setAttribute("stroke-opacity", 0.001);
  1731. line.setAttribute("stroke-dasharray", "none");
  1732. }
  1733. continue;
  1734. }
  1735.  
  1736. var wazeLineSeg = new WazeLineSegment(segment);
  1737. var lineMods = modifier.getModifiedAttrs(wazeLineSeg);
  1738. if((typeof lineMods === "undefined") || lineMods == null) {
  1739. continue;
  1740. }
  1741.  
  1742. var newColor = lineMods.color ? lineMods.color : currentColor;
  1743. line.setAttribute("stroke", newColor);
  1744.  
  1745. if (lineMods.color && lineMods.color != currentColor) {
  1746. }
  1747. if (lineMods.opacity && lineMods.opacity != currentOpacity) {
  1748. line.setAttribute("stroke-opacity", lineMods.opacity);
  1749. }
  1750. if (lineMods.dasharray && lineMods.dasharray != currentDashes) {
  1751. line.setAttribute("stroke-dasharray", lineMods.dasharray);
  1752. }
  1753. if (lineMods.width && lineMods.width != currentWidth) {
  1754. line.setAttribute("stroke-width", lineMods.width);
  1755. }
  1756. }
  1757. }
  1758. }
  1759.  
  1760. // add logged in user to drop-down list
  1761. function initUserList() {
  1762. var thisUser = Waze.loginManager.getLoggedInUser();
  1763. var selectUser = getId(highlightEditor.getSelectId());
  1764. var usrOption = document.createElement('option');
  1765. var usrText = document.createTextNode(thisUser.userName + " (" + thisUser.rank + ")");
  1766. usrOption.setAttribute('value', thisUser.id);
  1767. usrOption.appendChild(usrText);
  1768. selectUser.appendChild(usrOption);
  1769. }
  1770.  
  1771. function populateOption(selectId, optionsMap) {
  1772. var select = getId(selectId);
  1773. var currentId = null;
  1774. if (select.selectedIndex >= 0) {
  1775. currentId = select.options[select.selectedIndex].value;
  1776. }
  1777. select.options.length = 0;
  1778.  
  1779. var foundSelected = false;
  1780. for (var key in optionsMap) {
  1781. var text = optionsMap[key];
  1782. var selectOption = document.createElement('option');
  1783. var selectText = document.createTextNode(text);
  1784. if (currentId != null && key == currentId) {
  1785. selectOption.setAttribute('selected', true);
  1786. foundSelected = true;
  1787. }
  1788. selectOption.setAttribute('value', key);
  1789. selectOption.appendChild(selectText);
  1790. select.appendChild(selectOption);
  1791. }
  1792.  
  1793. }
  1794.  
  1795. // populate drop-down list of Cities
  1796. function populateCityList() {
  1797. var cityIds = new Object();
  1798. cityIds[WME_SPEED_UNKNOWN] = "No City";
  1799. for (var cit in Waze.model.cities.objects) {
  1800. var city = Waze.model.cities.get(cit);
  1801. if (city && cityIds[city.id] == null && city.name != null && city.name.length > 0) {
  1802. var cityName = city.name;
  1803. var state = Waze.model.states.get(city.stateID);
  1804. if(state && state.name != null && state.name.length > 0) {
  1805. cityName += ', ' + state.name;
  1806. }
  1807. cityIds[city.id] = cityName;
  1808. }
  1809. }
  1810. populateOption(highlightCity.getSelectId(), cityIds);
  1811. }
  1812.  
  1813. // populate drop-down list of editors
  1814. function populateUserList() {
  1815. var editorIds = new Object();
  1816. for (var seg in Waze.model.segments.objects) {
  1817. var segment = Waze.model.segments.get(seg);
  1818. var updatedBy = segment.attributes.updatedBy;
  1819. if (editorIds[updatedBy] == null) {
  1820. var user = Waze.model.users.get(updatedBy);
  1821. if (user == null || user.userName.match(/^world_|^usa_/) != null) {
  1822. continue;
  1823. }
  1824. editorIds[updatedBy] = user.userName;
  1825. }
  1826. }
  1827. populateOption(highlightEditor.getSelectId(), editorIds);
  1828. }
  1829.  
  1830. function createSectionHeader(title, opened) {
  1831. var indicator = "&lt;&lt;"
  1832. if(!opened) {
  1833. indicator = "&gt;&gt;"
  1834. }
  1835. return '<span style="font-size:1.2em;"><b>' + title + '</b></span><span style="float:right;padding:0;margin:0 0 0 2px;border: 1px solid #999; background: #aaa; color:#fff;">' + indicator + '</span>'
  1836. }
  1837.  
  1838. function createSection(sectionItem) {
  1839. var thisSectionItem = sectionItem;
  1840. // advanced options
  1841. var section = document.createElement('div');
  1842. section.style.marginTop = "4px";
  1843. section.style.padding = "4px";
  1844. section.style.borderStyle = "solid";
  1845. section.style.borderWidth = "1px";
  1846. section.style.borderColor = "#aaa";
  1847. section.id = thisSectionItem.id;
  1848. var aheader = document.createElement('div');
  1849. aheader.innerHTML = createSectionHeader(thisSectionItem.header, false);
  1850. aheader.style.display = 'block';
  1851. aheader.style.cursor = 'pointer';
  1852.  
  1853. section.appendChild(aheader);
  1854. var segmentsContainer = document.createElement('div');
  1855. segmentsContainer.style.display = 'none';
  1856. aheader.onclick = function() {
  1857. if(segmentsContainer.style.display == 'block') {
  1858. segmentsContainer.style.display = 'none';
  1859. aheader.innerHTML = createSectionHeader(thisSectionItem.header, false);
  1860. } else {
  1861. segmentsContainer.style.display = 'block';
  1862. aheader.innerHTML = createSectionHeader(thisSectionItem.header, true);
  1863. }
  1864. };
  1865. section.appendChild(segmentsContainer);
  1866. var modifiers = thisSectionItem.selections;
  1867. for (var i = 0; i < modifiers.length; i++) {
  1868. var segMod = modifiers[i];
  1869. var segmentContainer = document.createElement('div');
  1870. var segmentColor = document.createElement('div');
  1871. segmentColor.innerHTML="▶";
  1872. segmentColor.style.color = segMod.getBackground();
  1873. segmentColor.style.textShadow = "1px 1px 2px #333";
  1874. segmentColor.style.cssFloat = "left";
  1875. segmentColor.style.height = "100%";
  1876. segmentColor.style.lineHeight = "100%";
  1877. segmentColor.style.verticalAlign = "middle";
  1878. var segmentBuild = document.createElement('div');
  1879. var isChecked = window.localStorage.getItem(segMod.getCheckboxId()) === 'checked';
  1880. segmentBuild.innerHTML = segMod.build(isChecked);
  1881. segmentBuild.style.paddingLeft = "1.5em";
  1882. segmentContainer.appendChild(segmentColor);
  1883. segmentContainer.appendChild(segmentBuild);
  1884. // segmentContainer.style.background = segMod.getBackground();
  1885. segmentsContainer.appendChild(segmentContainer);
  1886. }
  1887. return section;
  1888. }
  1889.  
  1890. function toggleAddonVisible() {
  1891. var visibleElement = getId("highlight-addon");
  1892. if(visibleElement.style.display == "none") {
  1893. visibleElement.style.display = "block";
  1894. }
  1895. else {
  1896. visibleElement.style.display = "none";
  1897. }
  1898. }
  1899.  
  1900. var stylizer = document.createElement('style');
  1901. stylizer.innerHTML = "#WME_SPEED_addOnToggle{"
  1902. stylizer.innerHTML += generateTopDownGradient('#eeeeee', '#cccccc');
  1903. stylizer.innerHTML += "border: 1px solid #ccc; \
  1904. border-bottom: 1px solid #bbb; \
  1905. -webkit-border-radius: 3px; \
  1906. -moz-border-radius: 3px; \
  1907. -ms-border-radius: 3px; \
  1908. -o-border-radius: 3px; \
  1909. border-radius: 3px; \
  1910. color: #333; \
  1911. font: bold 11px 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Geneva, Verdana, sans-serif;\
  1912. padding: 0.1em 0.2em; \
  1913. text-shadow: 0 1px 0 #eee; \
  1914. width: 120px; } "
  1915. stylizer.innerHTML += "#WME_SPEED_addOnToggle:hover{ "
  1916. stylizer.innerHTML += generateTopDownGradient('#dddddd', '#bbbbbb');
  1917. stylizer.innerHTML += "border: 1px solid #bbb; \
  1918. border-bottom: 1px solid #999; \
  1919. cursor: pointer; \
  1920. text-shadow: 0 1px 0 #ddd; } "
  1921. stylizer.innerHTML +=
  1922. "#WME_SPEED_addOnToggle:active{ \
  1923. border: 1px solid #aaa; \
  1924. border-bottom: 1px solid #888; \
  1925. -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; \
  1926. -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; \
  1927. box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; \
  1928. } "
  1929. stylizer.innerHTML += "#WME_SPEED_Popup {background: #fff;position:absolute;bottom:48px;right:24px;}"
  1930. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container {text-align: center;font-size: 1.1em; margin: 1px; border:solid 1px #000;border-radius: 2px;}"
  1931. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container.locked {border:dashed 2px #f00;}"
  1932. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container.userlocked {border:solid 2px #f00;}"
  1933.  
  1934. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container #popup_street_name {font-size:.8em; margin:0;padding:0;line-height:1em;}"
  1935. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container #popup_street_name #street_name_prefix {font-size: .6em;vertical-align:middle;}"
  1936. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container #popup_street_name #street_name_suffix {font-size: .65em;vertical-align:top;}"
  1937.  
  1938. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container #popup_street_city {font-size:.8em;margin:1px 0 0 0;padding:0;line-height:1em;}"
  1939. stylizer.innerHTML += "#WME_SPEED_Popup .WME_SPEED_parkingLot, #WME_SPEED_Popup .WME_SPEED_privateStreet { background-color:#aaa;color:#000;font-style:italic;}"
  1940. stylizer.innerHTML += "#WME_SPEED_Popup .WME_SPEED_streetSign {background: #006F53; color:#fff;}"
  1941. stylizer.innerHTML += "#WME_SPEED_Popup .WME_SPEED_trailSign {background: #8C6019; color:#000; font-weight:bold;}"
  1942. stylizer.innerHTML += "#WME_SPEED_Popup .WME_SPEED_dirtRoadSign {background: #754546; color:#E2C99B; font-weight:normal;}"
  1943. stylizer.innerHTML += "#WME_SPEED_Popup .WME_SPEED_railroadSign {background: #fff; color:#000; font-weight:normal; border: solid 1px #000;}"
  1944. stylizer.innerHTML += "#WME_SPEED_Popup .WME_SPEED_unknownName {font-style:italic; }"
  1945. stylizer.innerHTML += "#WME_SPEED_Popup .WME_SPEED_alternateName {font-style:italic; border: solid 1px white; font-size:.7em;padding:0;line-height:.95em; }"
  1946. stylizer.innerHTML += "#WME_SPEED_Popup .WME_SPEED_parkingLotSign {\
  1947. height:21px;\
  1948. padding-right:17px;\
  1949. background-position:right center;\
  1950. background-repeat:no-repeat;\
  1951. background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAVCAYAAABR915hAAAACXBIWXMAAABPAAAATwFjiv3XAAACQElEQVR42sXWT2iUZxDH8c/srtu4zUGtVrBtpBaEokgNohR7CHjyYkvBkxXU2igpIoIgCB7EevQWxKiotILg0lLspdSqFy+CFMVDS0Gwaq0aSeK/YjTJ9LJqupBVE40Dz+Ed5nm/88wz83vf0OUe3vRs+xdXcRyd2Z5/GIMVXiC2gtn4GudjX6wZL/BwK0v7oiu+GC046kp9GWdGiG3Gx5g0bHe3Ju/nyrz/ouBS3fPpbM8VI2Z5MKZ55CcsAmmaBz7Hd6+01Lk6u7EK+dSpbVzuuNbNvcNcU8YFHPtjXh3s71cOjt3xniGH69rz7GjA9c21JLri1Aj9X1bSiqZh3n80qb4M8HRh+nMOYkobRzNKYxGQ+9LqbM/qaAWk/sT30N0g/pZwUujMtXl1LJJZDz7WSEBephW8Jntt4NIzm3dPzDXBtfwye+JQTPKgptNlF3JNXouuWJDr8mzsjVZFlwx62x1XNJvjLef8ZYKKluzI32N/vGvQfG843vDEUY2igqohm0C/DxVsVvSRAT/G9igLO2NPLMQ3PnBHWq+iRcEuvbaoaFHSEXtjqiFHhXke2tq41H2Woiq1RTXKtfkdlPprKh2oKDiMX7ItB/73x5IWK5pT+5gsEb7FAeGHxuAh67AUM/X5rPaCXsyQvs8N2Y9moQPLnyT3eDcbhJ21hHvxDlqlnwu4iRu1dftJmQ/EDNzSbqGJFkif4hF+028bPontUZL+zK/yVxzRYxnuKhpAn+suSp3SXZOdkGZhG3b8B9u3s4ceFzVrAAAAAElFTkSuQmCC');\
  1952. }"
  1953. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container #popup_street_name.WME_SPEED_interstate {background-color: #006F53; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAABnRSTlMA/wD/AP83WBt9AAAACXBIWXMAAAsTAAALEwEAmpwYAAADPElEQVR42rXWzWsTWxjH8e+cTgiTVNvEoi5sqvW1paCiFBciWKluAiKC4E7c6EKqCK5c+A8IbisqKCJuFAQ3roW6sCAl+NJILDY1jZnO5MWazOT1uYvJrVdvq6jTHwNz5uE5Hw4zzMzRRAQALMvqSCQYGiIQADRN8+rthnqdyUmUYv9+dH2ZhlpN3r5l9+5oNOrVde9ULpfDjx8b588TCjEwQG8vPT2EQjgOts3cHG/eUKkAhMMMDbFpE9EohkGlgmUxO8v0NI7z9e5d59QpwzAA5dFOLmdcuwawdy8bNpBO8/o1a9YwPc3Wreg6Y2Ps2MHZs+zZw65dGAavXvHoEZEIlQoHD3LkCNB59WrZND1TAYVCIXL7NrkcwPAwx49z8SKpFJUKPT0kk+g6tRojIwwOYll8+EAySTzO6CjFIhMT9PczMQGQyXTdv18qldp0q1zuuHWLpSSTbNny7bJYBNi8mRcvuHePkyfb9b4+Bgf594ZSq3nDwM2bDccBdMdxjGfPsKx2UyIBMDWF65JIYNscPcrLl4yPE4mwbx+Tk3z+TKvFgwd0dFCp0GhQLDIywtOnAJ8+BZ4/r584odm2/WWq6M7M419CA7HOgU4WFux16wT8PPr6xLZtlU5rto2/SafJ5zU1M4PvEeHdO1f5vmQvi4sB1WwGV8UmpAKB2mrAuu6qaFRWg167tqr6+/2nNY2dO4MqFmP9ep/p7dvp6kJpmvfN8jMeqILBYDzu+ksfO/Y1HA4jItmstXGjb295LCa5nCUiCggG1diYbw/z8uVmMKi3/2wiMju70Nvrw5K3bZNMZsEz23SpVHr4sPqXrqbJkyfO4uLid7SImKZ57txf0VeuiGmaS+A3utlsZrPW6OgfuvG4ZLMLrVZrGVpEXNf9+LFw6NBvu4cPy9xcoVar/Vf7jvb0TMY+ffo33DNnZH7edl33B+pHWkTq9XouZ46PN7u7f4FGo3LnTsM0zUaj8X9nGdqLbdup1JcLF8QwlkFDIbl0SVKpQj6fX0lYkRaRarVqWVYyWbh+XYaHRSlRSg4ckBs35P37vGVZ9Xr9J9O1pe3kSmk2m95uyLY1pYhEBOju7lZK/XziPwFBIyW1EjjMAAAAAElFTkSuQmCC'); background-repeat: no-repeat; background-position: center center; color:#fff;font-size:.92em;font-weight:bold;min-height:30px;vertical-align: 2px; line-height: 30px;margin: 0 auto;width: 100%}"
  1954. stylizer.innerHTML += ".WME_SPEED_interstate#popup_street_city { display: none; }";
  1955. stylizer.innerHTML += "#WME_SPEED_Popup #WME_SPEED_tollRoad {background: #FFC500; color:#000;font-size: .8em; text-transform: uppercase; font-weight: bold;}"
  1956.  
  1957.  
  1958.  
  1959. stylizer.innerHTML +=
  1960. "#WME_SPEED_Popup #popup_container #popup_speed { \
  1961. margin:0.2em auto; \
  1962. padding: 0.3em; \
  1963. text-align:center; \
  1964. border:solid 1px #000; \
  1965. border-radius: .2em; \
  1966. width:3.1em; \
  1967. line-height: 1;\
  1968. letter-spacing: 0.07em; \
  1969. }"
  1970. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container #popup_speed #popup_speed_header {font-size:0.65em;line-height:1.2em;margin-bottom:0.1em;padding:0;}"
  1971. stylizer.innerHTML += "#WME_SPEED_Popup #popup_container #popup_speed #popup_speed_value {\
  1972. font-size:2.0em;\
  1973. font-weight:bold;\
  1974. margin:0.0em;\
  1975. padding:0;\
  1976. display:block;}"
  1977.  
  1978.  
  1979. // add new box to the map
  1980. var addonContainer = document.createElement('section');
  1981. var clickBarContainer = document.createElement('div');
  1982. var clickBar = document.createElement('a');
  1983. clickBar.id = "WME_SPEED_addOnToggle"
  1984. clickBar.innerHTML = 'Show / Hide';
  1985. clickBar.style.textAlign = 'center';
  1986. clickBar.onclick = toggleAddonVisible;
  1987. clickBarContainer.style.margin = '0 auto';
  1988. clickBarContainer.style.textAlign = 'center';
  1989. clickBarContainer.style.minHeight = '1.2em';
  1990. clickBarContainer.appendChild(clickBar);
  1991. addonContainer.appendChild(clickBarContainer);
  1992.  
  1993. var addon = document.createElement('section');
  1994. addon.id = "highlight-addon";
  1995.  
  1996. addon.innerHTML = '<b>WME Speed</b> ' + version;
  1997.  
  1998. for(var i = 0; i < selectSections.length; i++) {
  1999. addon.appendChild(createSection(selectSections[i]));
  2000. }
  2001.  
  2002. var section = document.createElement('div');
  2003. section.innerHTML = '<button type="button" id="_cbRefreshButton">Refresh</button> ';
  2004. addon.appendChild(section);
  2005.  
  2006. addonContainer.style.fontSize = "0.8em";
  2007. addonContainer.style.margin = "8px";
  2008. addonContainer.style.background = "#fff"
  2009. addonContainer.style.border = "silver solid 1px";
  2010. addonContainer.style.position = "absolute";
  2011. addonContainer.style.bottom = "24px";
  2012. addonContainer.style.clear = "all";
  2013. addonContainer.style.padding = "12px";
  2014. addonContainer.style.mozBorderRadius = "5px";
  2015. addonContainer.style.webkitBorderRadius = "5px";
  2016. addonContainer.style.borderRadius = "5px";
  2017. addonContainer.style.boxShadow = "2px 2px 5px #000"
  2018. addonContainer.appendChild(addon);
  2019.  
  2020. getId('editor-container').appendChild(stylizer);
  2021. getId('editor-container').appendChild(addonContainer);
  2022.  
  2023. debug("Hi There")
  2024.  
  2025. // check for AM or CM, and unhide Advanced options
  2026. var advancedMode = false;
  2027. if (Waze.loginManager != null) {
  2028. thisUser = Waze.loginManager.getLoggedInUser();
  2029. if (thisUser != null && thisUser.normalizedLevel >= 4) {
  2030. advancedMode = true;
  2031. // initUserList();
  2032. populateUserList();
  2033. populateCityList();
  2034. }
  2035. }
  2036.  
  2037. // setup onclick handlers for instant update:
  2038. getId('_cbRefreshButton').onclick = highlightAllSegments;
  2039. enumerateAllModifiers(function(seg) {
  2040. seg.init();
  2041. });
  2042.  
  2043.  
  2044.  
  2045. function createWazeMapEventAction(actionName) {
  2046. debug("register createWazeMapEventAction(actionName)");
  2047. return function() {
  2048. setTimeout(function() {
  2049. highlightAllSegments();
  2050. // showPopup();
  2051.  
  2052. }, 50);
  2053. return true;
  2054. };
  2055. }
  2056.  
  2057. function analyzeNodes() {
  2058. var wazeNodes = new Object();
  2059. for (var wazeNode in Waze.model.nodes.objects) {
  2060. var attachedSegments = [];
  2061. for(var wazeSegID in wazeNode.data.segIDs) {
  2062. attachedSegments.push(Waze.model.segments.objects[wazeSegID]);
  2063. }
  2064. wazeNodes[wazeNode.fid] = new WazeNode(wazeNode, attachedSegments);
  2065. }
  2066. }
  2067.  
  2068. function createEventAction(eventHolderName, actionName) {
  2069. debug("register createEventAction(eventHolderName, actionName)");
  2070. return function() {
  2071. highlightAllSegments();
  2072. populateUserList();
  2073. populateCityList();
  2074. // showPopup();
  2075. return true;
  2076. };
  2077. }
  2078.  
  2079. function createHighlighAction(eventHolderName, actionName) {
  2080. debug("register createHighlighAction(eventHolderName, actionName)");
  2081. return function(e) {
  2082. if(e.feature)
  2083. {
  2084. highlightSegmentMonitor.updateLatestSegment(e.feature);
  2085. showPopup(e.feature);
  2086. highlightSegments(hoverDependentSections);
  2087. return true;
  2088. }
  2089. };
  2090. }
  2091.  
  2092. var loadFunction = function(e) {
  2093. debug("event listener for load");
  2094. thisUser = Waze.loginManager.getLoggedInUser();
  2095. if (!advancedMode && thisUser.normalizedLevel >= 4) {
  2096. advancedMode = true;
  2097. populateUserList();
  2098. populateCityList();
  2099. }
  2100. for (var i = 0; i < possibleControllerEvents.length; i++) {
  2101. var eventName = possibleControllerEvents[i];
  2102. Waze.controller.events.register(eventName, this, createEventAction("controller", eventName));
  2103. }
  2104. for (var i = 0; i < possibleWazeMapEvents.length; i++) {
  2105. var eventName = possibleWazeMapEvents[i];
  2106. Waze.map.events.register(eventName, this, createWazeMapEventAction(eventName));
  2107. }
  2108. for (var i = 0; i < possiblePendingControllerEvents.length; i++) {
  2109. var eventName = possiblePendingControllerEvents[i];
  2110. pendingControl.events.register(eventName, this, createEventAction("pendingControl", eventName));
  2111. }
  2112. for (var i = 0; i < possibleSelectionModifyEvents.length; i++) {
  2113. var eventName = possibleSelectionModifyEvents[i];
  2114. // selectionManager.modifyControl.events.register(eventName, this, createEventAction("selectionManager.modifyControl", eventName));
  2115. }
  2116. for (var i = 0; i < possibleSelectionEvents.length; i++) {
  2117. var eventName = possibleSelectionEvents[i];
  2118. Waze.selectionManager.events.register(eventName, this, createEventAction("selectionManager", eventName));
  2119. }
  2120. for (var i = 0; i < possibleSelectionModifyHoverEvents.length; i++) {
  2121. var eventName = possibleSelectionModifyHoverEvents[i];
  2122. // selectionManager.modifyControl.featureHover.control.events.register(eventName, this, createEventAction("selectionManager.modifyControl.featureHover.control", eventName));
  2123. }
  2124. for (var i = 0; i < possibleActionEvents.length; i++) {
  2125. var eventName = possibleActionEvents[i];
  2126. Waze.model.actionManager.events.register(eventName, this, createEventAction("Waze.model.actionManager", eventName));
  2127. }
  2128. Waze.selectionManager.selectControl.events.register("featurehighlighted", this, createHighlighAction("selectionManager.selectControl", "featurehighlighted"));
  2129.  
  2130. if(DEBUG) {
  2131. Waze.selectionManager.registerModelEvents("selectionChanged", this, function(){console.log("sm.blur")});
  2132. Waze.selectionManager.events.register("touchstart", this, function(){console.log("sm.mc.touchstart")});
  2133. //Waze.selectionManager.layers[0].events.register("beforefeatureselected", this, function(){console.log("sm.mc.beforefeatureselected")});
  2134. // Waze.selectionManager.selectControl.events.register("featurehighlighted", this, function(e){console.log("sm.mc.featurehighlighted : ");});
  2135. // selectionManager.modifyControl.featureHover.control.events.register("activate", this, function(){console.log("sm.mc.fh.c.activate")});
  2136. // selectionManager.modifyControl.featureHover.control.events.register("mouseover", this, function(){console.log("sm.mc.fh.c.mouseover")});
  2137. // selectionManager.modifyControl.featureHover.register("over", this, function(){console.log("sm.mc.fh.-e.over")});
  2138. }
  2139. }
  2140.  
  2141. debug("registering for events for when window is marked as loaded");
  2142. if(document.readyState === "complete") {
  2143. debug("Already Loaded");
  2144. loadFunction("");
  2145. }
  2146. else {
  2147. window.addEventListener("load", loadFunction);
  2148. Waze.app._events.register("change:loading", loadFunction);
  2149. }
  2150. // trigger code when page is fully loaded, to catch any missing bits
  2151.  
  2152. }
  2153. wmeSpeedBootstrap();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址