您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds colours to road segments to show their status
当前为
// ==UserScript== // @name WME Color Highlights // @namespace http://userscripts.org/users/419370 // @description Adds colours to road segments to show their status // @include https://www.waze.com/editor/* // @include https://www.waze.com/*/editor/* // @include https://editor-beta.waze.com/* // @version 1.91 // @grant none // ==/UserScript== var wmech_version = "1.91" /* bootstrap, will call initialiseHighlights() */ function bootstrapHighlights() { var bGreasemonkeyServiceDefined = false; try { bGreasemonkeyServiceDefined = (typeof Components.interfaces.gmIGreasemonkeyService === "object"); } catch (err) { /* Ignore */ } if (typeof unsafeWindow === "undefined" || ! bGreasemonkeyServiceDefined) { unsafeWindow = ( function () { var dummyElem = document.createElement('p'); dummyElem.setAttribute('onclick', 'return window;'); return dummyElem.onclick(); }) (); } /* begin running the code! */ setTimeout(initialiseHighlights, 999); } // set of 'bad names' to flag on UK roads only // if editing for another country, search for 234 var badNames = [ ' (Av|Avenue)$', ' Ch$', // chase ' (Crt|Court|Close|Cls)$', ' (Cres|Crescent|Crs)$', ' (Drv|Drive)$', ' (Gardens?|Grdns?)$', // optional s ' (Grn|Green|Grove)$', ' (Grv|Grove|Place)$', ' (Lane|Road|Street)$', ' (Te|Tce|Terr|Terrace)$', ' (Wk|Wy)$', // Walk|Way '[.]$', // anything ending in . '^[a-z]+| [a-z]{3}', // missing capitals ' By-[Pp]ass', // Bypass '^([AB]\\d+ - )?St ', // Saint (St.) '^[AB]\\d+ : ', // Colon instead of dash '^[AB]\\d+( |-| -?[A-Za-z])', // double or missing space, or missing hyphen ' \\([AB]\\d+\\)$' // ending in (A123) ]; var reBadNames = new RegExp(badNames.join('|'), ''); var goodNames = [ '^([AB]\\d+.* - )?The (Avenue|Boulevard|Broadway|Bypass|Circus|Close|Court|Crescent|Drive)$', '^([AB]\\d+.* - )?The (Gardens?|Green|Groves?|Lane|Mount|Place|Park|Ridge|Square|Street|Terrace|Valley)$' ]; var reGoodNames = new RegExp(goodNames.join('|'), ''); /* =========================================================================== */ function highlightSegments() { var showLocked = getId('_cbHighlightLocked').checked; var showToll = getId('_cbHighlightToll').checked; var showNoCity = getId('_cbHighlightNoCity').checked; var showNoName = getId('_cbHighlightUnnamed').checked; var showOneWay = getId('_cbHighlightOneWay').checked; var showNoDirection = getId('_cbHighlightNoDirection').checked; var showRestrictions = getId('_cbHighlightRestrictions').checked; var specificCity = getId('_cbHighlightCity').checked; var specificCityInvert = getId('_cbHighlightCityInvert').checked; var specificRoadType = getId('_cbHighlightRoadType').checked; var showNoTerm = getId('_cbHighlightNoTerm').checked; var showRecent = advancedMode ? getId('_cbHighlightRecent').checked : false; var specificEditor = advancedMode ? getId('_cbHighlightEditor').checked : false; //var showHouseNums = advancedMode ? getId('_cbHighlightHouseNums').checked : false; var showPlaces = getId('_cbHighlightPlaces').checked; var tNow = new Date(); var numDays; var selectedUserId = null; var selectedCityId = null; if (specificEditor) { var selectUser = getId('_selectUser'); if (selectUser.selectedIndex >= 0) selectedUserId = selectUser.options[selectUser.selectedIndex].value; else specificEditor = false; } if (specificCity) { var selectCity = getId('_selectCity'); if (selectCity.selectedIndex >= 0) selectedCityId = selectCity.options[selectCity.selectedIndex].value; else specificCity = false; } if (specificRoadType) { var selectRoadType = getId('_selectRoadType'); if (selectRoadType.selectedIndex >= 0) selectedRoadType = selectRoadType.options[selectRoadType.selectedIndex].value; else specificRoadType = false; } if (showRecent) { numDays = getId('_numRecentDays').value; if (numDays === undefined) numDays = 0; } // counters var numUserHighlighted = 0; var numCityHighlighted = 0; for (var seg in Waze.model.segments.objects) { var segment = Waze.model.segments.get(seg); var attributes = segment.attributes; var line = getId(segment.geometry.id); if (line !== null) { var sid = attributes.primaryStreetID; // check that WME hasn't highlighted this segment var opacity = line.getAttribute("stroke-opacity"); var lineWidth = line.getAttribute("stroke-width"); if (opacity == 1 || lineWidth == 9) continue; // turn off highlights when roads are no longer visible var roadType = attributes.roadType; if (Waze.map.zoom <= 3 && (roadType < 2 || roadType > 7) ) { if (opacity > 0.1) { line.setAttribute("stroke","#dd7700"); line.setAttribute("stroke-opacity",0.001); line.setAttribute("stroke-dasharray", "none"); } continue; } // highlight all newly paved roads (or roads without any nodes) if (sid === null || (attributes.toNodeID === null && attributes.fromNodeID === null && roadType < 9)) { if (opacity < 0.1) { line.setAttribute("stroke","#f00"); line.setAttribute("stroke-opacity",0.75); line.setAttribute("stroke-width", 10); } continue; } var street = Waze.model.streets.get(sid); // get attributes for this segment var toll = attributes.fwdToll; var locked = attributes.lockRank > 0; var ranked = attributes.rank > 0; var noEdit = attributes.permissions == 0; var noName = (street != null) && street.isEmpty; var badName = !noName && street.name.match(reBadNames) && !street.name.match(reGoodNames); var cityID = (street != null) && street.cityID; var noCity = false; var countryID = 0; if (cityID != null && Waze.model.cities.get(cityID) != null) { noCity = Waze.model.cities.get(cityID).isEmpty; countryID = Waze.model.cities.get(cityID).countryID; } var oneWay = ((attributes.fwdDirection + attributes.revDirection) == 1); // it is 1-way only if either is true var noDirection = (!attributes.fwdDirection && !attributes.revDirection); // Could use the .attribute.allowNoDirection? var hasRestrictions = (attributes.fwdRestrictions.length + attributes.revRestrictions.length > 0); var updatedOn = new Date(attributes.updatedOn); var updatedBy = attributes.updatedBy; var roundabout = attributes.junctionID !== null; var tDif = (tNow.getTime() - updatedOn.getTime()) / 86400000; // get current state of the line var lineColor = line.getAttribute("stroke"); // default colours var newColor = "#dd7700"; var newOpacity = 0.001; var newDashes = "none"; var newWidth = 8; // Recent Edits within X days, with decaying green opacity if (showRecent && numDays >= 0 && tDif <= numDays) { if ((updatedBy == selectedUserId) || (!specificEditor)) { var heatScale = 0.75 / numDays; newColor = "#0f0"; newOpacity = Math.min(0.999999, 1 - (tDif * heatScale)); } } // Toll = Dashed else if (toll && showToll) { newColor = "#00f"; newOpacity = 0.5; newDashes = "10 10"; } // No Edit = Black else if (noEdit && showLocked) { newColor = "#000"; newOpacity = 0.75; newWidth = 3; } // Locked = Red else if (locked && showLocked) { newColor = "#f00"; newWidth = 6; newOpacity = 0.2 * Math.min(5, attributes.lockRank); } else if (ranked && showLocked) { newColor = "#f00"; newWidth = 6; newDashes = "2 8"; newOpacity = 0.2 * Math.min(5, attributes.rank); } else if (hasRestrictions && showRestrictions) { newColor = "#909"; newDashes = "10 10"; newOpacity = 0.5; } // bad roundabouts = Lime //else if (roundabout && (!oneWay || !noName) && showNoTerm) { // newColor = "#BE0"; // newOpacity = 0.5; //} // Unnamed (No Name) = Orange // except roundabouts and non-Streets else if (noName && showNoName && !roundabout && attributes.roadType < 8) { newColor = "#fb0"; newOpacity = 0.5; } // bad names (UK only) = Orange dashed else if ((badName || !noName && roundabout) && showNoName && countryID == 234 && attributes.roadType != 4) { newColor = "#fb0"; newOpacity = 0.5; newDashes = "10 10"; newWidth = 6; } // No City = Gray else if (noCity && showNoCity) { newColor = "#888"; newOpacity = 0.5; } // No Direction = Cyan else if (noDirection && showNoDirection) { newColor = "#0ff"; newOpacity = 0.3; } // One Way = Blue else if (oneWay && showOneWay) { newColor = "#00f"; newOpacity = 0.2; } // Unterminated segments: no end node or not connected = Lime else if (showNoTerm && (attributes.toNodeID === null || attributes.fromNodeID === null || attributes.toNodeID === attributes.fromNodeID) && attributes.length > 10) { newColor = "#BE0"; newOpacity = 0.5; } //else if (showHouseNums && attributes.hasHNs) { // newColor = "#4E4"; // newOpacity = 0.5; //} // selected road type = purple else if (specificRoadType && attributes.roadType == selectedRoadType) { newColor = "#909"; newOpacity = 0.5; newWidth = 4; } // special road types: non-drivable / non-routable else if (specificRoadType && selectedRoadType == 98 && nonRoutableTypes.contains(attributes.roadType)) { newColor = "#909"; newOpacity = 0.5; newWidth = 4; } else if (specificRoadType && selectedRoadType == 99 && nonDrivableTypes.contains(attributes.roadType)) { newColor = "#909"; newOpacity = 0.5; newWidth = 4; } // highlight segments by selected user, unless already highlighted if (specificEditor && !showRecent) { if (updatedBy == selectedUserId && newColor == "#dd7700") { newColor = "#00ff00"; newOpacity = 0.5; numUserHighlighted++; } else if (updatedBy != selectedUserId) { newColor = "#dd7700"; newOpacity = 0.001; newDashes = "none"; } } // highlight segments by selected City, unless already highlighted // if city is only on an alternate street highlight it with dashes if (specificCity) { var altCityMatch = false; var specificCityMatch = (cityID == selectedCityId); if (specificCityInvert) specificCityMatch = (cityID != selectedCityId && !noCity); if (!specificCityMatch) { // look for matching city in alternate streets for (var i in attributes.streetIDs) { var streetID = attributes.streetIDs[i]; var currentStreet = Waze.model.streets.get(streetID); if (currentStreet == null) continue; var match = (currentStreet.cityID == selectedCityId); if (specificCityInvert) match = !match if (match) { altCityMatch = true; break; } } } if (specificCityMatch && (newColor == "#dd7700" || newColor == "#888")) { newColor = "#ff0"; newOpacity = 0.75; newDashes = "none"; numCityHighlighted++; } else if (altCityMatch && (newColor == "#dd7700" || newColor == "#888")) { newColor = "#ffff01"; newOpacity = 0.75; newDashes = "10 10"; newWidth = 6; numCityHighlighted++; } else if (!specificCityMatch && !altCityMatch && !noCity) { newColor = "#dd7700"; newOpacity = 0.001; newDashes = "none"; } } // highlight railroads (as Places) if (showPlaces && attributes.roadType == 18) { newColor = "#444"; newOpacity = 0.8; newDashes = "4 12"; newWidth = 3; } // if colour has changed, update the line attributes if (lineColor != newColor) { line.setAttribute("stroke", newColor); line.setAttribute("stroke-opacity", newOpacity); line.setAttribute("stroke-dasharray", newDashes); if (newColor != "#dd7700") { //default line.setAttribute("stroke-width", newWidth); } else { line.setAttribute("stroke-width", 6); } } } // end if (line !== null) } // end of loop numUserHighlightedText = getId('_numUserHighlighted'); if (specificEditor) numUserHighlightedText.innerHTML = ' = ' + numUserHighlighted; else numUserHighlightedText.innerHTML = ''; numCityHighlightedText = getId('_numCityHighlighted'); if (specificCity) numCityHighlightedText.innerHTML = ' = ' + numCityHighlighted; else numCityHighlightedText.innerHTML = ''; } // end of function function highlightPlaces() { if (typeof Waze.model.venues == "undefined") { return; } // if checkbox unticked, reset places to original style if (!getId('_cbHighlightPlaces').checked) { for (var mark in Waze.model.venues.objects) { var venue = Waze.model.venues.get(mark); var poly = getId(venue.geometry.id); if (poly !== null) { if (poly.getAttribute("fill-opacity") != 0.3) { poly.setAttribute("fill","#d191d6"); poly.setAttribute("stroke","#d191d6"); poly.setAttribute("fill-opacity",0.3); poly.setAttribute("stroke-opacity",1); } } } return; } var specificCity = getId('_cbHighlightCity').checked; var specificCityInvert = getId('_cbHighlightCityInvert').checked; if (specificCity) { var selectCity = getId('_selectCity'); if (selectCity.selectedIndex >= 0) { selectedCityId = selectCity.options[selectCity.selectedIndex].value; } else specificCity = false; } for (var mark in Waze.model.venues.objects) { var venue = Waze.model.venues.get(mark); var poly = getId(venue.geometry.id); if (poly !== null && venue.geometry.toString().match(/^POLYGON/)) { venueStreet = Waze.model.streets.get(venue.attributes.streetID); selectedCityMatch = (specificCity && venueStreet.cityID == selectedCityId); if (specificCityInvert) selectedCityMatch = !selectedCityMatch; // highlight places which have the City field set in the address = yellow if (poly.getAttribute("fill") != "#ff8") { if (specificCity && selectedCityMatch) { poly.setAttribute("fill","#ff8"); poly.setAttribute("stroke","#cc0"); } } // if was yellow and now not yellow, reset else if (!specificCity || !selectedCityMatch) { poly.setAttribute("fill","#d191d6"); poly.setAttribute("stroke","#d191d6"); } if (poly.getAttribute("fill") == "#d191d6" && poly.getAttribute("fill-opacity") == 0.3) { var categories = venue.attributes.categories; // gas station = orange if (categories.indexOf("GAS_STATION") > -1) { poly.setAttribute("fill","#f90"); poly.setAttribute("stroke","#f90"); } // parking lot = cyan else if (categories.indexOf("PARKING_LOT") > -1) { poly.setAttribute("fill","#099"); poly.setAttribute("stroke","#0cc"); } // water = blue else if (categories.indexOf("RIVER_STREAM") > -1 || categories.indexOf("SEA_LAKE_POOL") > -1) { poly.setAttribute("fill","#09f"); poly.setAttribute("stroke","#06c"); } // park/grass/trees = green else if (categories.indexOf("PARK") > -1 || categories.indexOf("FARM") > -1 || categories.indexOf("FOREST_GROVE") > -1 || categories.indexOf("GOLF_COURSE") > -1) { poly.setAttribute("fill","#4f4"); poly.setAttribute("stroke","#6a6"); } poly.setAttribute("fill-opacity",0.28); } } } } function highlightSelectedNodes() { if (Waze.map.zoom <= 3 || !advancedMode) return true; var showTurns = advancedMode ? getId('_cbHighlightTurns').checked : false; // look for a selected node or segment (there can only be 1) var currentNodes = []; var selectType = ''; if (Waze.selectionManager.selectedItems.length == 1) { var selection = Waze.selectionManager.selectedItems[0]; if (selection !== null) { if (selection.state == "Update" && lastModified == false) { lastSelected = null; lastModified = true; } else if (selection.state != "Update" && lastModified == true) { lastSelected = null; lastModified = false; } selectType = selection.type; if (selection.type == "node") { currentNodes.push(selection.fid); } else if (selection.type == "segment") { currentNodes.push(selection.attributes.fromNodeID); currentNodes.push(selection.attributes.toNodeID); } } } // selection changed, then reset previous highlights | selectType == 'node' if ((lastSelected != currentNodes[0] || !showTurns) && selectedLines.length > 0) { for (var i = 0; i < selectedLines.length; i++) { line = getId(selectedLines[i]); if (line !== null && line.getAttribute("stroke-width") == 8) line.setAttribute("stroke-opacity", 0.0001); } selectedLines = []; } // no node selected, quit now if (currentNodes.length === 0) { lastSelected = null; lastModified = false; return true; } var numSoftTurns = 0; var numRevConns = 0; var numUTurns = 0; var showWarning = false; for (var i = 0; i < currentNodes.length; i++) { var currentNode = currentNodes[i]; var node = Waze.model.nodes.get(currentNode); if (node === undefined) continue; // ignore dead-end nodes if (node.attributes.segIDs.length <= 1) { lastSelected = currentNode[0]; continue; } // find segments that connect to this node for (var j = 0; j < node.attributes.segIDs.length; j++) { var segID = node.attributes.segIDs[j]; var segment = Waze.model.segments.get(segID); if (segment === undefined) continue; var attributes = segment.attributes; var line = getId(segment.geometry.id); if (line === null || line === undefined) continue; var newColor = null; var n = (attributes.fromNodeID == currentNode) ? 1 : 0; // n = 0 for fwd, 1 for rev // check for soft-turns var nodeLocked = (n == 0) ? attributes.fwdTurnsLocked : attributes.revTurnsLocked; if (nodeLocked === false) { newColor = "#ff0"; // yellow numSoftTurns++; } // highlight reverse connectivity and nodes that are causing it in purple if (attributes.fwdDirection == true && attributes.revDirection == false) { // one way A->B for (var key in node.attributes.connections) { var val = node.attributes.connections[key]; var connSegs = key.split(","); var checkseg = (n == 0) ? connSegs[1] : connSegs[0]; if (val == true && checkseg == segID) { newColor = "#f0f"; numRevConns++; } } } if (attributes.fwdDirection == false && attributes.revDirection == true) { // one way A<-B for (var key in node.attributes.connections) { var val = node.attributes.connections[key]; var connSegs = key.split(","); var checkseg = (n == 0) ? connSegs[0] : connSegs[1]; if (val == true && checkseg == segID) { newColor = "#f0f"; numRevConns++; } } } if (attributes.fwdDirection == true && attributes.revDirection == true) { // two-way, check for connections back to the same segment if (node.attributes.segIDs.length > 1) { for (var key in node.attributes.connections) { var val = node.attributes.connections[key]; var connSegs = key.split(","); if (val == true && connSegs[0] == segID && connSegs[1] == segID) { newColor = "#0ff"; numUTurns++; } } } } var oldOpacity = line.getAttribute("stroke-opacity"); if (newColor !== null && oldOpacity < 1 && showTurns) { line.setAttribute("stroke", newColor); line.setAttribute("stroke-opacity", 1); line.setAttribute("stroke-width", 8); line.setAttribute("stroke-dasharray", "none"); selectedLines.push(segment.geometry.id); } if (newColor !== null) showWarning = true; } } if (currentNodes.length > 0) { var currentNode = currentNodes[0]; if (showWarning === true) { // setup new box for warnings about this node var selectionBox; if (selectType == 'segment') selectionBox = getId('segment-edit-general'); else selectionBox = getId('node-edit-general'); var nodeDetails = getId('nodeTipsBox'); if (!nodeDetails) { nodeDetails = document.createElement('div'); nodeDetails.id = 'nodeTipsBox'; selectionBox.appendChild(nodeDetails); } else { return; nodeDetails.innerHTML = ''; } if (numSoftTurns > 0) { nodeText = document.createElement('div'); if (selectType == 'node') nodeText.title = "Press Q and then re-enable each allowed turn."; else nodeText.title = "Select individual nodes to see details."; nodeText.style.padding = "4px 2px"; nodeText.innerHTML = "<b>Warning:</b> " + selectType + " has " + numSoftTurns + " soft turns."; nodeText.style.backgroundColor = '#ffc'; nodeDetails.appendChild(nodeText); } if (numRevConns > 0) { nodeText = document.createElement('div'); if (selectType == 'node') nodeText.title = "Press Q and then re-enable each allowed turn."; else nodeText.title = "Select individual nodes to see details."; nodeText.style.padding = "4px 2px"; nodeText.innerHTML = "<b>Warning:</b> " + selectType + " has " + numRevConns + " reverse connections."; nodeText.style.backgroundColor = '#fcf'; nodeDetails.appendChild(nodeText); } if (numUTurns > 0) { nodeText = document.createElement('div'); nodeText.title = "Use the U-Turn arrows to set when a U-Turn is allowed."; nodeText.style.padding = "4px 2px"; nodeText.innerHTML = "<b>Notice:</b> " + selectType + " has " + numUTurns + " U-Turns."; nodeText.style.backgroundColor = '#cff'; nodeDetails.appendChild(nodeText); } if (selectType == 'node') { nodeText = document.createElement('div'); nodeText.style.padding = "4px 2px"; nodeText.innerHTML = '<br>'; if (typeof unsafeWindow.WME_JNF_Version != "undefined") { nodeText.innerHTML += '<span style="float:right">[<a href="http://userscripts.org/scripts/show/144939" target="_blank">JNF '+unsafeWindow.WME_JNF_Version+'</a>]</span>'; if (typeof unsafeWindow.WME_JNF_FixNode == "function") { nodeText.innerHTML += '<i><a href="#" id="_autoFixLink">' + 'Automatically fix this node</a></i> (Q)<br>'; } else { nodeText.innerHTML += "<i style='color: red'>JNF script not active. Upgrade!</i><br>"; } } else { nodeText.innerHTML += '<i>Hover over text above for help.</i><br>'; } nodeText.innerHTML += '<i>For a full explanation, <a href="http://waze.cryosphere.co.uk/node-help" target="_blank">see this page</a>.</i><br>'; nodeDetails.appendChild(nodeText); autoFixLink = getId('_autoFixLink'); if (autoFixLink != null) { autoFixLink.onclick = autoFixNode; } } } } lastSelected = currentNodes[0]; return true; } function autoFixNode() { currentNode = Waze.selectionManager.selectedItems[0]; unsafeWindow.WME_JNF_FixNode(currentNode); return false; } /* display average speed for selected segments (code by bgodette) */ /* no longer used */ function extraDetails() { if (!advancedMode) return; if (Waze.selectionManager.selectedItems.length == 1) { var selection = Waze.selectionManager.selectedItems[0]; if (selection) { if (selection.type == "segment") { segeditgen = document.getElementById("segment-edit-general"); segextra = document.getElementById("segment-extra-details"); if (!segextra) { segextra = document.createElement('div'); segextra.id = 'segment-extra-details'; segeditgen.appendChild(segextra); } var fwdSpeed = selection.attributes.fwdCrossSpeed; var revSpeed = selection.attributes.revCrossSpeed; var editTime = new Date(selection.attributes.updatedOn); segextra.innerHTML = "<br><u title=\"*Additional data displayed by Color Highlights Script\">Average speed for segment</u>*<br>" + " A->B: " + fwdSpeed + "km/h (" + Math.round(fwdSpeed * 6.21371) / 10 + "mph)<br>" + " B->A: " + revSpeed + "km/h (" + Math.round(revSpeed * 6.21371) / 10 + "mph)<br>" + "Segment Rank: " + (selection.attributes.rank + 1) + " cones<br>" + "<i>" + editTime.toTimeString() + "</i>"; } } } return true; } function highlightBadNodes() { if (Waze.map.zoom <= 3 || !advancedMode) return true; var showTurns = advancedMode ? getId('_cbHighlightTurns').checked : false; var showRestrictions = getId('_cbHighlightRestrictions').checked; for (var currentNode in Waze.model.nodes.objects) { var node = Waze.model.nodes.get(currentNode); if (node === undefined) continue; var numRestrictions = 0; var numSoftTurns = 0; var numRevConns = 0; var numUTurns = 0; // ignore dead-end nodes if (node.attributes.segIDs.length <= 1) { continue; } // find segments that connect to this node for (var j = 0; j < node.attributes.segIDs.length; j++) { var segID = node.attributes.segIDs[j]; var segment = Waze.model.segments.get(segID); if (segment === undefined) continue; var attributes = segment.attributes; // count restictions if (showRestrictions) { for (var key in node.attributes.restrictions) { if (key) numRestrictions++; } } if (attributes.roadType < 2 || attributes.roadType > 7) continue; // only look at Primary Streets and above var n = (attributes.fromNodeID == currentNode) ? 1 : 0; // n = 0 for fwd, 1 for rev // check for soft-turns var nodeLocked = (n == 0) ? attributes.fwdTurnsLocked : attributes.revTurnsLocked; if (nodeLocked === false) { numSoftTurns++; } // highlight reverse connectivity and nodes that are causing it in purple if (attributes.fwdDirection == true && attributes.revDirection == false) { // one way A->B for (var key in node.attributes.connections) { var val = node.attributes.connections[key]; var connSegs = key.split(","); var checkseg = (n == 0) ? connSegs[1] : connSegs[0]; if (val == true && checkseg == segID) { numRevConns++; } } } if (attributes.fwdDirection == false && attributes.revDirection == true) { // one way A<-B for (var key in node.attributes.connections) { var val = node.attributes.connections[key]; var connSegs = key.split(","); var checkseg = (n == 0) ? connSegs[0] : connSegs[1]; if (val == true && checkseg == segID) { numRevConns++; } } } if (attributes.fwdDirection == true && attributes.revDirection == true) { // two-way, check for connections back to the same segment if (node.attributes.segIDs.length > 1) { for (var key in node.attributes.connections) { var val = node.attributes.connections[key]; var connSegs = key.split(","); if (val == true && connSegs[0] == segID && connSegs[1] == segID) { numUTurns++; } } } } } var newColor = null; if (numUTurns > 0) newColor = "#0ff"; else if (numRevConns > 0) newColor = "#f0f"; else if (numRestrictions > 0) newColor = "#909"; var circle = getId(node.geometry.id); if (newColor != null && circle != null) { opacity = circle.getAttribute("fill-opacity"); if (opacity < 0.1) { circle.setAttribute("fill-opacity", 0.75); circle.setAttribute("fill", newColor); } } } return true; } // add logged in user to drop-down list function initUserList() { if (!advancedMode) return; var thisUser = Waze.loginManager.user; if (thisUser === null) return; var selectUser = getId('_selectUser'); var usrOption = document.createElement('option'); var usrRank = thisUser.normalizedLevel; var usrText = document.createTextNode(thisUser.userName + " (" + usrRank + ")"); usrOption.setAttribute('value',thisUser.id); usrOption.appendChild(usrText); selectUser.appendChild(usrOption); console.log("WME Highlights: Init User list: " + thisUser.userName); } // add current city in to drop-down list function initCityList() { var locationInfo = Waze.map.getControlsByClass('Waze.Control.LocationInfo')[0]; if (locationInfo === null || locationInfo.location === null) return; var cityName = locationInfo.location.city; var thisCity = null; for (var city in Waze.model.cities.objects) { var cityObj = Waze.model.cities.get(city); if (cityObj.name == cityName) { thisCity = cityObj.id; break; } } if (thisCity === null) return; var selectCity = getId('_selectCity'); var cityOption = document.createElement('option'); var cityText = document.createTextNode(cityName); cityOption.appendChild(cityText); cityOption.setAttribute('value',thisCity); selectCity.appendChild(cityOption); console.log("WME Highlights: Init City list: " + cityName); // stop listening for this event Waze.model.events.unregister("mergeend", null, initCityList); } // populate drop-down list of editors function updateUserList() { // update list of users - for high zoom and AMs only if (Waze.map.zoom <= 3 || !advancedMode) return; var selectUser = getId('_selectUser'); var numUsers = Waze.model.users.objects.length; if (numUsers === 0) return; // preserve current selection var currentId = null; if (selectUser.selectedIndex >= 0) currentId = selectUser.options[selectUser.selectedIndex].value; // collect array of users who have edited segments var editorIds = []; for (var seg in Waze.model.segments.objects) { var segment = Waze.model.segments.get(seg); if (getId(segment.geometry.id) === null) continue; var updatedBy = segment.attributes.updatedBy; if (editorIds.indexOf(updatedBy) == -1) editorIds.push(updatedBy); } editorIds.sort(); if (editorIds.length === 0) return; // reset list selectUser.options.length = 0; // add all users in field of view for (var i = 0; i < editorIds.length; i++) { var id = editorIds[i]; var user = Waze.model.users.get(id); if (user === null || typeof(user) === "undefined") continue; var usrOption = document.createElement('option'); var usrRank = user.normalizedLevel; var usrText = document.createTextNode(user.userName + " (" + usrRank + ")"); if (currentId !== null && id == currentId) usrOption.setAttribute('selected',true); usrOption.setAttribute('value',id); usrOption.appendChild(usrText); selectUser.appendChild(usrOption); } } // populate drop-down list of Cities function updateCityList() { var selectCity = getId('_selectCity'); var numCities = Waze.model.cities.objects.length; if (numCities === 0) return; // preserve current selection var currentId = null; if (selectCity.selectedIndex >= 0) currentId = selectCity.options[selectCity.selectedIndex].value; // collect array of Cities var cityIds = []; var cityObjs = []; //========================================================================================= // This new block of code checks the following assumed conditions: // * Every U.S. city should have an associated state // * Every 'No city' U.S. city should be properly numbered (not an orphan blank city) // * We only care about states if get.cities shows us close enough to the U.S. to matter // * Any non US's city state code should be 99 (None/other) //======================================================================================== // collect list if unique cities from the segments for (var sid in Waze.model.streets.objects) { var cid = Waze.model.streets.get(sid).cityID; var city = Waze.model.cities.get(cid); if (cityIds.indexOf(cid) == -1) { cityIds.push(cid); cityObjs.push({id: city.id, name: city.name, state: city.stateID, country: city.countryID}); } } if (cityIds.length === 0) return; // reset list selectCity.options.length = 0; // count how many (non empty) states there are here var numStates = 0 for (var obj in Waze.model.states.objects) { state = Waze.model.states.get(obj); if (state.id != 1 && state.name != "") numStates++; } // count how many countries there are here var numCountries = 0; for (var obj in Waze.model.countries.objects) { numCountries++; } // add all cities in field of view cityObjs.sort(function(a,b){return (a.name < b.name) ? -1 : (a.name > b.name) ? 1 : 0;}); for (var i = 0; i < cityObjs.length; i++) { var cityID = cityObjs[i].id; // "State-like CityIDs" to ignore. These are consistently over 100,000,000. if (cityID > 100000000) continue; var cityName = cityObjs[i].name; var stateID = cityObjs[i].state; var countryID = cityObjs[i].country; if (countryID == 235) { // for U.S. only // 'No City' segments in the U.S. should have an assigned state. // This ID has a prescribed range. If not in this range, we get 'other' state pollution in map, // or a bogus blank city associated to the state. if (cityName === "") { if (cityID >= 999900 && cityID <= 999999) { cityName = "No City"; } else { cityName = "EMPTY CITY"; } } } else { // for non U.S. segments if (cityName === "") cityName = "No City"; } var stateObj = Waze.model.states.get(stateID); var countryObj = Waze.model.countries.get(countryID); // State handling. All cities should have an associated state. Throw an error if not. if (numStates > 0) { // If more than one state, we're appending it. No brainer. if (numStates > 1) { // ... and, if one of those states is 'Other', that's an error. Report it. if (stateObj.id === 99) { cityName += ", " + "NO STATE"; } // If we get here, the state ID should be fine. Append it. else { cityName += ", " + stateObj.name; } } // If we have more than one country and are in the US, append the state for sanity. if (numStates == 1 && numCountries > 1) { cityName += ", " + stateObj.name; } } // If we're on a non-US street, state should always be 99, 'Other/none'. // Append if this is the case. Otherwise don't add anything. else if (stateID != 99 && stateID > 1) { cityName += ", INVALID STATE"; } if (numCountries > 1) { cityName += ", " + countryObj.name.replace('United States', 'U.S.'); } // create option in select menu var cityOption = document.createElement('option'); var cityText = document.createTextNode(cityName); if (currentId !== null && cityID == currentId) cityOption.setAttribute('selected',true); cityOption.setAttribute('value',cityID); cityOption.appendChild(cityText); selectCity.appendChild(cityOption); } } var RoadTypes = { 1: "Streets", 21: "Service Road", 98: "Non-Routable Roads", // -------------- 108: "- Dirt roads", 120: "- Parking Lot Road", 117: "- Private Road", 199: "Non-Drivable Roads", // -------------- 210: "- Pedestrian Bw", 205: "- Walking Trails", 216: "- Stairway", 219: "- Runway/Taxiway" // 2: "Primary Street", // 3: "Freeways", // 4: "Ramps", // 6: "Major Highway", // 7: "Minor Highway", // 18: "Railroad", }; var nonRoutableTypes = new Array(8, 20, 17); var nonDrivableTypes = new Array(10, 5, 16, 19); // populate drop-down list of editors function populateRoadTypes() { var selectRoadType = getId('_selectRoadType'); for (var id in RoadTypes) { var type = RoadTypes[id] var usrOption = document.createElement('option'); var usrText = document.createTextNode(type); if (id == 1) usrOption.setAttribute('selected',true); usrOption.setAttribute('value',id % 100); usrOption.appendChild(usrText); selectRoadType.appendChild(usrOption); } } function toggleOptions () { var objStyle = getId('hiliteOptions').style.display; if (objStyle == "none") { objStyle = "block"; getId('_btnHide').innerHTML = "hide"; } else { objStyle = "none"; getId('_btnHide').innerHTML = "show"; } getId('hiliteOptions').style.display = objStyle; if (advancedMode) getId('advancedOptions').style.display = objStyle; getId('hilitePlaces').style.display = objStyle; return false; } // enable advanced options if user is logged in and at least an AM function enableAdvancedOptions() { if (advancedMode) return; if (typeof Waze == 'undefined') Waze = unsafeWindow.Waze; if (typeof Waze.loginManager == 'undefined') Waze.loginManager = unsafeWindow.Waze.loginManager; if (typeof Waze.loginManager == 'undefined') Waze.loginManager = unsafeWindow.loginManager; if (Waze.loginManager !== null && Waze.loginManager.isLoggedIn()) { thisUser = Waze.loginManager.user; if (thisUser !== null && thisUser.normalizedLevel >= 3) { Waze.loginManager.events.unregister("afterloginchanged", null, enableAdvancedOptions); console.log('WME Highlights: Advanced Options enabled for ' + thisUser.userName); getId('advancedOptions').style.display = 'block'; advancedMode = true; initUserList(); initCityList(); } } } /* helper function */ function getElementsByClassName(classname, node) { if(!node) node = document.getElementsByTagName("body")[0]; var a = []; var re = new RegExp('\\b' + classname + '\\b'); var els = node.getElementsByTagName("*"); for (var i=0,j=els.length; i<j; i++) if (re.test(els[i].className)) a.push(els[i]); return a; } function getId(node) { return document.getElementById(node); } /* =========================================================================== */ function initialiseHighlights() { // global variables advancedMode = false; betaMode = location.hostname.match(/editor-beta.waze.com/); lastSelected = null; lastModified = false; selectedLines = []; // add new box to left of the map var addon = document.createElement('section'); addon.id = "highlight-addon"; if (navigator.userAgent.match(/Chrome/)) { addon.innerHTML = '<b><a href="https://chrome.google.com/webstore/detail/wme-color-highlights/ijnldkoicbhinlgnoigchihmegdjobjc" target="_blank"><u>' + 'WME Colour Highlights</u></a></b> v' + wmech_version; } else { addon.innerHTML = '<b><a href="https://gf.qytechs.cn/scripts/3206-wme-color-highlights" target="_blank"><u>' + 'WME Colour Highlights</u></a></b> v' + wmech_version; + ' <a href="https://gf.qytechs.cn/scripts/3206-wme-color-highlights" target="_blank">' + '<img src="http://waze.cryosphere.co.uk/scripts/update.php?version=' + wmech_version + '" /></a>'; } // highlight segements var section = document.createElement('p'); section.style.paddingTop = "8px"; section.style.textIndent = "16px"; section.id = "hiliteOptions"; section.innerHTML = '<b>Highlight Segments</b><br>' + '<input type="checkbox" id="_cbHighlightLocked" /> <span title="Dotted = Automatic Locks (if available)">Locks*</span> (Red)<br>' + '<input type="checkbox" id="_cbHighlightToll" /> Toll (Dashed)<br>' + '<input type="checkbox" id="_cbHighlightUnnamed" /> No Name (Orange)<br>' + '<input type="checkbox" id="_cbHighlightNoCity" /> No City (Gray)<br>' + '<input type="checkbox" id="_cbHighlightOneWay" /> One Way (Blue)<br>' + '<input type="checkbox" id="_cbHighlightNoDirection" /> Unknown Direction (Cyan)<br>' + '<input type="checkbox" id="_cbHighlightRestrictions" /> Time/Vehicle Restrictions (Purple)<br>' + '<input type="checkbox" id="_cbHighlightNoTerm" /> <span title="*Dead-end roads should have terminating nodes on the end, or Waze cannot route to or from them.">Unterminated Roads* (Lime)</span><br>' + '<input type="checkbox" id="_cbHighlightCity" /> Filter by City (Yellow) ' + '<input type="checkbox" id="_cbHighlightCityInvert" /> invert <br> ' + ' <select id="_selectCity" name="_selectCity" style="margin: 0 0 4px 16px"></select>' + '<span id="_numCityHighlighted"></span><br>' + '<input type="checkbox" id="_cbHighlightRoadType" /> Highlight a Road Type (Purple)<br> ' + ' <select id="_selectRoadType" name="_selectRoadType" style="margin: 0 0 4px 16px"></select><br>' ; addon.appendChild(section); // advanced options section = document.createElement('p'); section.style.paddingTop = "8px"; section.style.textIndent = "16px"; section.style.display = "none"; section.id = 'advancedOptions'; section.innerHTML = '<b>Advanced Options</b><br>' + '<input type="checkbox" id="_cbHighlightRecent" /> Recently Edited (Green)<br> ' + ' <input type="number" min="0" max="365" size="3" id="_numRecentDays" style="margin: 0 0 4px 16px"/> days<br>' + '<input type="checkbox" id="_cbHighlightEditor" /> Filter by Editor (Green)<br> ' + ' <select id="_selectUser" name="_selectUser" style="margin: 0 0 4px 16px"></select>' + '<span id="_numUserHighlighted"></span><br>' + '<input type="checkbox" id="_cbHighlightTurns" /> <span title="*Highlight turn errors when a segment or node is selected, and on mjor roads">Turn Warnings for Selected Nodes*</span><br>' //'<input type="checkbox" id="_cbHighlightHouseNums" /> <span>Segments with House Numbers</span><br>' ; addon.appendChild(section); // highlight places section = document.createElement('p'); section.style.padding = "8px 16px"; section.style.textIndent = "-16px"; section.id = "hilitePlaces"; section.innerHTML = '<input type="checkbox" id="_cbHighlightPlaces" /> <b title="' + 'parks/trees = green, water = blue, parking lot = cyan, ' + 'everything else = pink">Highlight Places</b><br>'; addon.appendChild(section); var userTabs = getId('user-info'); var navTabs = getElementsByClassName('nav-tabs', userTabs)[0]; var tabContent = getElementsByClassName('tab-content', userTabs)[0]; newtab = document.createElement('li'); newtab.innerHTML = '<a href="#sidepanel-highlights" data-toggle="tab">Highlight</a>'; navTabs.appendChild(newtab); addon.id = "sidepanel-highlights"; addon.className = "tab-pane"; tabContent.appendChild(addon); // check for AM or CM, and unhide Advanced options enableAdvancedOptions(); // always populate road types populateRoadTypes(); // setup onclick handlers for instant update: getId('_cbHighlightLocked').onclick = highlightSegments; getId('_cbHighlightToll').onclick = highlightSegments; getId('_cbHighlightUnnamed').onclick = highlightSegments; getId('_cbHighlightNoCity').onclick = highlightSegments; getId('_cbHighlightOneWay').onclick = highlightSegments; getId('_cbHighlightNoDirection').onclick = highlightSegments; getId('_cbHighlightRestrictions').onclick = highlightSegments; getId('_cbHighlightRecent').onclick = highlightSegments; getId('_cbHighlightEditor').onclick = highlightSegments; getId('_cbHighlightCity').onclick = highlightSegments; getId('_cbHighlightCityInvert').onclick = highlightSegments; getId('_cbHighlightRoadType').onclick = highlightSegments; getId('_cbHighlightNoTerm').onclick = highlightSegments; getId('_cbHighlightTurns').onclick = highlightSelectedNodes; //getId('_cbHighlightHouseNums').onclick = highlightSegments; getId('_selectUser').onfocus = updateUserList; getId('_selectUser').onchange = highlightSegments; getId('_selectCity').onfocus = updateCityList; getId('_selectCity').onchange = highlightSegments; getId('_selectRoadType').onchange = highlightSegments; getId('_cbHighlightPlaces').onclick = highlightPlaces; // restore saved settings if (localStorage.WMEHighlightScript) { console.log("WME Highlights: loading options"); options = JSON.parse(localStorage.WMEHighlightScript); getId('_cbHighlightLocked').checked = options[1]; getId('_cbHighlightToll').checked = options[2]; getId('_cbHighlightUnnamed').checked = options[3]; getId('_cbHighlightNoCity').checked = options[4]; getId('_cbHighlightOneWay').checked = options[5]; getId('_cbHighlightNoDirection').checked = options[6]; getId('_cbHighlightNoTerm').checked = options[14]; getId('_cbHighlightCity').checked = options[15]; getId('_cbHighlightRoadType').checked = options[16]; getId('_selectRoadType').selectedIndex = options[17]; getId('_cbHighlightPlaces').checked = options[7]; getId('_cbHighlightRestrictions').checked = options[19]; if (options[12] === undefined) options[12] = 7; getId('_cbHighlightRecent').checked = options[11]; getId('_numRecentDays').value = options[12]; getId('_cbHighlightEditor').checked = options[13]; getId('_cbHighlightTurns').checked = options[18]; //getId('_cbHighlightHouseNums').checked= options[19]; } else { getId('_cbHighlightPlaces').checked = true; getId('_cbHighlightTurns').checked = true; } if (typeof Waze.model.venues == "undefined") { getId('_cbHighlightPlaces').checked = false; getId('_cbHighlightPlaces').disabled = true; } // overload the WME exit function saveHighlightOptions = function() { if (localStorage) { console.log("WME Highlights: saving options"); var options = []; // preserve previous options which may get lost after logout if (localStorage.WMEHighlightScript) options = JSON.parse(localStorage.WMEHighlightScript); options[1] = getId('_cbHighlightLocked').checked; options[2] = getId('_cbHighlightToll').checked; options[3] = getId('_cbHighlightUnnamed').checked; options[4] = getId('_cbHighlightNoCity').checked; options[5] = getId('_cbHighlightOneWay').checked; options[6] = getId('_cbHighlightNoDirection').checked; options[14] = getId('_cbHighlightNoTerm').checked; options[15] = getId('_cbHighlightCity').checked; options[16] = getId('_cbHighlightRoadType').checked; options[17] = getId('_selectRoadType').selectedIndex; options[7] = getId('_cbHighlightPlaces').checked; options[19] = getId('_cbHighlightRestrictions').checked; if (advancedMode) { options[11] = getId('_cbHighlightRecent').checked; options[12] = getId('_numRecentDays').value; options[13] = getId('_cbHighlightEditor').checked; options[18] = getId('_cbHighlightTurns').checked; //options[19] = getId('_cbHighlightHouseNums').checked; } localStorage.WMEHighlightScript = JSON.stringify(options); } } window.addEventListener("beforeunload", saveHighlightOptions, false); // begin periodic updates window.setInterval(highlightSegments,333); window.setInterval(highlightPlaces,500); window.setInterval(highlightBadNodes,444); window.setInterval(highlightSelectedNodes,250); // trigger code when page is fully loaded, to catch any missing bits window.addEventListener("load", function(e) { var mapProblems = getId('map-problems-explanation') if (mapProblems !== null) mapProblems.style.display = "none"; enableAdvancedOptions(); }); // register some events... Waze.map.events.register("zoomend", null, highlightSegments); Waze.map.events.register("zoomend", null, highlightPlaces); Waze.map.events.register("zoomend", null, highlightSelectedNodes); Waze.selectionManager.events.register("selectionchanged", null, highlightSelectedNodes); //Waze.selectionManager.events.register("selectionchanged", null, extraDetails); Waze.loginManager.events.register("afterloginchanged", null, enableAdvancedOptions); Waze.model.events.register("mergeend", null, initCityList); } /* engage! =================================================================== */ bootstrapHighlights(); /* end ======================================================================= */
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址