WME PlaceNames

Show area and point place names in WME, color and highlight places by type and properties

目前为 2014-11-29 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name WME PlaceNames
  3. // @version 0.5
  4. // @description Show area and point place names in WME, color and highlight places by type and properties
  5. // @include https://www.waze.com/editor/*
  6. // @include https://www.waze.com/*/editor/*
  7. // @include https://editor-beta.waze.com/editor/*
  8. // @include https://editor-beta.waze.com/*/editor/*
  9. // @copyright 2014, ragacs
  10. // @namespace https://gf.qytechs.cn/users/6330
  11. // ==/UserScript==
  12.  
  13. var wmepn_version = "0.5";
  14.  
  15. // Using parts from highlight and route speed scripts by various authors
  16.  
  17. /* bootstrap, will call initialiseLandmarkNames() */
  18. function bootstrapLandmarkNames()
  19. {
  20. var bGreasemonkeyServiceDefined = false;
  21.  
  22. try {
  23. bGreasemonkeyServiceDefined = (typeof Components.interfaces.gmIGreasemonkeyService === "object");
  24. }
  25. catch (err) { /* Ignore */ }
  26.  
  27. if (typeof unsafeWindow === "undefined" || ! bGreasemonkeyServiceDefined) {
  28. unsafeWindow = ( function () {
  29. var dummyElem = document.createElement('p');
  30. dummyElem.setAttribute('onclick', 'return window;');
  31. return dummyElem.onclick();
  32. }) ();
  33. }
  34.  
  35. /* begin running the code! */
  36. setTimeout(initialiseLandmarkNames, 999);
  37. }
  38.  
  39. function wmepn_wordWrap(str, maxWidth) {
  40. function testWhite(x) {
  41. var white = new RegExp(/^[ \t\r\n\f]$/); // We are not using \s because it matches non-breaking space too
  42. return white.test(x.charAt(0));
  43. }
  44.  
  45. var newLineStr = "\n"; done = false; res = '';
  46. do {
  47. found = false;
  48. // Inserts new line at first whitespace of the line
  49. for (i = maxWidth - 1; i >= 0; i--) {
  50. if (testWhite(str.charAt(i))) {
  51. res = res + [str.slice(0, i), newLineStr].join('');
  52. str = str.slice(i + 1);
  53. found = true;
  54. break;
  55. }
  56. }
  57. // Inserts new line at maxWidth position, the word is too long to wrap
  58. if (!found && str.length > maxWidth) {
  59. res += [str.slice(0, maxWidth), newLineStr].join('');
  60. str = str.slice(maxWidth);
  61. }
  62.  
  63. if (str.length < maxWidth)
  64. {
  65. res = res + str;
  66. done = true;
  67. }
  68. } while (!done);
  69.  
  70. return res;
  71. }
  72.  
  73. function wmepn_resetLandmarks()
  74. {
  75. var venues = Waze.model.venues;
  76. for (var mark in venues.objects) {
  77. var venue = venues.get(mark);
  78. var poly = wmepn_getId(venue.geometry.id);
  79. if (poly !== null) {
  80. if (poly.getAttribute("stroke-opacity") != 1) {
  81. poly.setAttribute("fill","#d191d6");
  82. poly.setAttribute("stroke","#d191d6");
  83. poly.setAttribute("fill-opacity",0.3);
  84. poly.setAttribute("stroke-opacity",1);
  85. }
  86. }
  87. }
  88. wmepn_showLandmarkNames();
  89. }
  90.  
  91. function wmepn_showLandmarkNames() {
  92. wmepn_NameLayer.removeAllFeatures();
  93. if (typeof Waze.model.venues == "undefined" || wmepn_getId('_cbLandmarkNamesEnable').checked == false) {
  94. return;
  95. }
  96. var venues = Waze.model.venues;
  97. var streets = Waze.model.streets;
  98. var map = Waze.map;
  99. var showNames = wmepn_NameLayer.getVisibility() && map.getLayersBy("uniqueName", "landmarks")[0].getVisibility();
  100. // if checkbox unticked, reset places to original style
  101. if (!showNames
  102. && !wmepn_getId('_cbLandmarkColors').checked
  103. && !wmepn_getId('_cbLandmarkHiliteNoName').checked) {
  104. for (var mark in venues.objects) {
  105. var venue = venues.get(mark);
  106. var poly = wmepn_getId(venue.geometry.id);
  107. if (poly !== null) {
  108. if (poly.getAttribute("stroke-opacity") != 1) {
  109. poly.setAttribute("fill","#d191d6");
  110. poly.setAttribute("stroke","#d191d6");
  111. poly.setAttribute("fill-opacity",0.3);
  112. poly.setAttribute("stroke-opacity",1);
  113. }
  114. }
  115. }
  116. return;
  117. }
  118.  
  119. var hiliteNoName = wmepn_getId('_cbLandmarkHiliteNoName').checked;
  120. var colorLandmarks = wmepn_getId('_cbLandmarkColors').checked;
  121. var showPoints = (wmepn_getId('_seLandmarkPoints').value == "all" || wmepn_getId('_seLandmarkPoints').value == "point");
  122. var showAreas = (wmepn_getId('_seLandmarkPoints').value == "all" || wmepn_getId('_seLandmarkPoints').value == "area");
  123. var nameFilterArray = wmepn_getId('_inLandmarkNameFilter').value.split("/");
  124. var nameFilter = (nameFilterArray.length > 1 ? nameFilterArray[1] : nameFilterArray[0]);
  125. var nameFilterOptions = nameFilterArray[2];
  126. var nameFilterRegEx = (nameFilterArray.length > 1 ? new RegExp(nameFilter, nameFilterOptions) : null);
  127. var doFilter = function (name) {
  128. if(nameFilter.length == 0)
  129. return true; // show all when no filter entered
  130. if(nameFilterRegEx == null)
  131. return (name.indexOf(nameFilter) >= 0);
  132. else
  133. return nameFilterRegEx.test(name);
  134. }
  135.  
  136. for (var mark in venues.objects) {
  137. var venue = venues.get(mark);
  138. var poly = wmepn_getId(venue.geometry.id);
  139. var isPoint = venue.geometry.toString().match(/^POINT/);
  140. var isArea = venue.geometry.toString().match(/^POLYGON/);
  141. var trimmedName = venue.attributes.name.trim();
  142. var houseNumber = venue.attributes.houseNumber;
  143. if (poly !== null) {
  144. var venueStreet = streets.get(venue.attributes.streetID);
  145. var haveNoName = (venue.attributes.residential ? (houseNumber.length == 0) : (trimmedName.length == 0));
  146.  
  147. if(showNames && (showAreas || showPoints))
  148. {
  149. var wrappedText = wmepn_wordWrap(trimmedName, 30);
  150. var filterMatched = (trimmedName.length > 0 && doFilter(trimmedName));
  151. if(showAreas && isArea && filterMatched)
  152. {
  153. // Add label texts
  154. var labelFeatures = [];
  155. var bounds = venue.geometry.bounds;
  156. var pt;
  157. //if(bounds.getWidth() * bounds.getHeight() * .3 > venue.geometry.getArea() && venue.attributes.entryExitPoints.length > 0)
  158. // pt = venue.attributes.entryExitPoints[0].point;
  159. //else
  160. pt = venue.geometry.getCentroid();
  161. var textFeature = new OpenLayers.Feature.Vector( pt, {labelText: wrappedText, fontColor: '#F0F0F0', pointRadius: 0 } );
  162. labelFeatures.push(textFeature);
  163. wmepn_NameLayer.addFeatures(labelFeatures);
  164. }
  165. if(showPoints && isPoint && (filterMatched || (houseNumber !== undefined && houseNumber.length > 0)))
  166. {
  167. // Add label texts
  168. var labelFeatures = [];
  169. var pt = new OpenLayers.Geometry.Point(venue.geometry.x, venue.geometry.y);
  170. var isHouseNumber = !filterMatched;
  171. var textFeature = new OpenLayers.Feature.Vector( pt, {labelText: (isHouseNumber ? houseNumber : wrappedText), fontColor: '#F0F0F0', pointRadius: 0, yOffset: -15, style: (isHouseNumber ? "italic" : "normal") } );
  172. labelFeatures.push(textFeature);
  173. wmepn_NameLayer.addFeatures(labelFeatures);
  174. }
  175. }
  176. // Production polygons: #d191d6, Beta editor polygons: #c290c6
  177. if ((poly.getAttribute("fill") == "#d191d6" || poly.getAttribute("fill") == "#c290c6") && poly.getAttribute("stroke-opacity") == 1) {
  178. var categories = venue.attributes.categories;
  179. var colored = false;
  180. if(colorLandmarks)
  181. {
  182. // gas station = orange
  183. if (categories.indexOf("GAS_STATION") > -1) {
  184. poly.setAttribute("fill","#f90");
  185. poly.setAttribute("stroke","#f90");
  186. colored = true;
  187. }
  188. // parking lot = cyan
  189. else if (categories.indexOf("PARKING_LOT") > -1) {
  190. poly.setAttribute("fill","#099");
  191. poly.setAttribute("stroke","#0cc");
  192. }
  193. // water = blue
  194. else if (categories.indexOf("RIVER_STREAM") > -1 ||
  195. categories.indexOf("SEA_LAKE_POOL") > -1) {
  196. poly.setAttribute("fill","#09f");
  197. poly.setAttribute("stroke","#06c");
  198. colored = true;
  199. }
  200. // park/grass/trees = green
  201. else if (categories.indexOf("PARK") > -1 ||
  202. categories.indexOf("FARM") > -1 ||
  203. categories.indexOf("FOREST_GROVE") > -1 ||
  204. categories.indexOf("GOLF_COURSE") > -1) {
  205. poly.setAttribute("fill","#4f4");
  206. poly.setAttribute("stroke","#6a6");
  207. colored = true;
  208. }
  209. }
  210.  
  211. poly.setAttribute("stroke-opacity",0.97);
  212. // highlight places which have no name and not colored before
  213. if (hiliteNoName && haveNoName && colored == false) {
  214. poly.setAttribute("fill","#ff8");
  215. poly.setAttribute("stroke","#cc0");
  216. colored = true;
  217. }
  218. // if was yellow and now not yellow, reset
  219. else if (poly.getAttribute("fill") == "#ff8" && (!hiliteNoName || !haveNoName)) {
  220. poly.setAttribute("fill","#d191d6");
  221. poly.setAttribute("stroke","#d191d6");
  222. poly.setAttribute("stroke-opacity",1);
  223. }
  224. }
  225. }
  226. }
  227. }
  228.  
  229. function wmepn_toggleOptions () {
  230. return false;
  231. }
  232.  
  233. /* helper function */
  234. function wmepn_getId(node) {
  235. return document.getElementById(node);
  236. }
  237.  
  238. /* =========================================================================== */
  239.  
  240. function initialiseLandmarkNames()
  241. {
  242. // global variables
  243. wmepn_betaMode = location.hostname.match(/editor-beta.waze.com/);
  244. wmepn_NameLayer = undefined;
  245.  
  246. // helper fn
  247. function getElementsByClassName(classname, node) {
  248. if(!node) node = document.getElementsByTagName("body")[0];
  249. var a = [];
  250. var re = new RegExp('\\b' + classname + '\\b');
  251. var els = node.getElementsByTagName("*");
  252. for (var i=0,j=els.length; i<j; i++)
  253. if (re.test(els[i].className)) a.push(els[i]);
  254. return a;
  255. }
  256.  
  257. // add new box to left of the map
  258. var addon = document.createElement('section');
  259. var map = unsafeWindow.Waze.map;
  260. addon.id = "landmarkname-addon";
  261.  
  262. if (navigator.userAgent.match(/Chrome/)) {
  263. addon.innerHTML = '<b>'
  264. + '<a href="https://www.waze.com/forum/viewtopic.php?f=819&t=116843" target="_blank">WME PlaceNames</a></b> &nbsp; v' + wmepn_version;
  265. } else {
  266. addon.innerHTML = '<b>'
  267. + '<a href="https://www.waze.com/forum/viewtopic.php?f=819&t=116843" target="_blank">WME PlaceNames</a></b> &nbsp; v' + wmepn_version;
  268. }
  269.  
  270. // highlight landmarks
  271. section = document.createElement('p');
  272. section.style.padding = "8px 16px";
  273. //section.style.textIndent = "-16px";
  274. section.id = "nameLandmarks";
  275. section.innerHTML = '<div title="Toggle highlighting and place names layer\nUse the Layer selector or Shift+N hotkey to toggle names only"><input type="checkbox" id="_cbLandmarkNamesEnable" /> <b>Enable script</b></div>'
  276. + '<div title="Color the places like WMECH does"><input type="checkbox" id="_cbLandmarkColors" /> <b>Color places</b></div>'
  277. + '<div title="Highlight public places without name and private places without house number (yellow)"><input type="checkbox" id="_cbLandmarkHiliteNoName"/> <b>Highlight places without name/HN</b></div>'
  278. + '<div title="Select desired names to show"><b>Show</b> <select id="_seLandmarkPoints">'
  279. + '<option value="area">Area only</option>'
  280. + '<option value="all">Area and Point</option>'
  281. + '<option value="point">Point only</option></select></div>'
  282. + '<div title="Filter only the names containing this string (you could use regex e.g. /school/i)"><b>Filter:</b><input type="text" id="_inLandmarkNameFilter"/></div>';
  283. addon.appendChild(section);
  284.  
  285. var userTabs = wmepn_getId('user-info');
  286. var navTabs = getElementsByClassName('nav-tabs', userTabs)[0];
  287. var tabContent = getElementsByClassName('tab-content', userTabs)[0];
  288.  
  289. newtab = document.createElement('li');
  290. newtab.innerHTML = '<a href="#sidepanel-landmarknames" data-toggle="tab">PlaceNames</a>';
  291. navTabs.appendChild(newtab);
  292.  
  293. addon.id = "sidepanel-landmarknames";
  294. addon.className = "tab-pane";
  295. tabContent.appendChild(addon);
  296.  
  297. // setup onclick handlers for instant update:
  298. wmepn_getId('_cbLandmarkColors').onclick = wmepn_resetLandmarks;
  299. wmepn_getId('_cbLandmarkHiliteNoName').onclick = wmepn_resetLandmarks;
  300. wmepn_getId('_seLandmarkPoints').onchange = wmepn_resetLandmarks;
  301. wmepn_getId('_cbLandmarkNamesEnable').onclick = wmepn_resetLandmarks;
  302. wmepn_getId('_inLandmarkNameFilter').oninput = wmepn_showLandmarkNames;
  303.  
  304. // Create PlaceName layer
  305. var rlayers = map.getLayersBy("uniqueName","__DrawPlaceNames");
  306. if(rlayers.length == 0) {
  307. var lname = "Place Names";
  308. var style = new unsafeWindow.OpenLayers.Style({
  309. strokeDashstyle: 'solid',
  310. strokeColor : "${strokeColor}",
  311. strokeOpacity: 1.0,
  312. strokeWidth: "${strokeWidth}",
  313. fillColor: '#0040FF',
  314. fillOpacity: 1.0,
  315. pointRadius: "${pointRadius}",
  316. label : "${labelText}",
  317. fontFamily: "Tahoma, Courier New",
  318. labelOutlineColor: '#FFEEEE',
  319. labelOutlineWidth: 2,
  320. labelAlign: 'cm',
  321. fontColor: "#301130",
  322. fontOpacity: 1.0,
  323. fontSize: "11px",
  324. display: 'block',
  325. labelYOffset: "${yOffset}",
  326. fontStyle: "${style}"
  327. });
  328. var nameLayer = new unsafeWindow.OpenLayers.Layer.Vector(lname, {
  329. displayInLayerSwitcher: true,
  330. uniqueName: "__DrawPlaceNames",
  331. shortcutKey: "S+n",
  332. accelerator: "toggle" + lname.replace(/\s+/g,''),
  333. styleMap: new unsafeWindow.OpenLayers.StyleMap(style)
  334. });
  335. nameLayer.setVisibility(true);
  336. //drc_mapLayer1.moveLayerToTop();
  337. map.addLayer(nameLayer);
  338. //var zLandmarks = map.getLayersBy("uniqueName", "landmarks")[0].getZIndex();
  339. //var zPlaceNames = drc_mapLayer1.getZIndex();
  340. //map.getLayersBy("uniqueName", "landmarks")[0].setZIndex(zPlaceNames);
  341. //drc_mapLayer1.setZIndex(zLandmarks);
  342. wmepn_NameLayer = nameLayer;
  343. }
  344. else wmepn_NameLayer = rlayers[0];
  345. // restore saved settings
  346. if (localStorage.WMELandmarkNamesScript) {
  347. console.log("WME LandmarkNames: loading options");
  348. options = JSON.parse(localStorage.WMELandmarkNamesScript);
  349.  
  350. wmepn_getId('_cbLandmarkColors').checked = options[1];
  351. wmepn_getId('_cbLandmarkHiliteNoName').checked = options[2];
  352. wmepn_getId('_seLandmarkPoints').value = options[3];
  353. wmepn_NameLayer.setVisibility(options[4]);
  354. if(options[5] !== undefined)
  355. wmepn_getId('_cbLandmarkNamesEnable').checked = options[5];
  356. else wmepn_NameLayer.setVisibility(true);
  357. if(options[6] !== undefined)
  358. wmepn_getId('_inLandmarkNameFilter').value = options[6];
  359. } else {
  360. wmepn_getId('_cbLandmarkColors').checked = true;
  361. wmepn_getId('_cbLandmarkHiliteNoName').checked = true;
  362. wmepn_getId('_seLandmarkPoints').value = "area";
  363. wmepn_NameLayer.setVisibility(true);
  364. wmepn_getId('_cbLandmarkNamesEnable').checked = true;
  365. }
  366.  
  367. if (typeof Waze.model.venues == "undefined") {
  368. wmepn_getId('_cbLandmarkColors').checked = false;
  369. wmepn_getId('_cbLandmarkHiliteNoName').checked = false;
  370. wmepn_getId('_cbLandmarkColors').disabled = true;
  371. wmepn_getId('_cbLandmarkHiliteNoName').disabled = true;
  372. wmepn_getId('_seLandmarkPoints').disabled = true;
  373. }
  374.  
  375. // overload the WME exit function
  376. wmepn_saveLandmarkNamesOptions = function() {
  377. if (localStorage) {
  378. console.log("WME LandmarkNames: saving options");
  379. var options = [];
  380.  
  381. // preserve previous options which may get lost after logout
  382. if (localStorage.WMELandmarkNamesScript)
  383. options = JSON.parse(localStorage.WMELandmarkNamesScript);
  384. options[1] = wmepn_getId('_cbLandmarkColors').checked;
  385. options[2] = wmepn_getId('_cbLandmarkHiliteNoName').checked;
  386. options[3] = wmepn_getId('_seLandmarkPoints').value;
  387. options[4] = wmepn_NameLayer.getVisibility();
  388. options[5] = wmepn_getId('_cbLandmarkNamesEnable').checked;
  389. options[6] = wmepn_getId('_inLandmarkNameFilter').value;
  390. localStorage.WMELandmarkNamesScript = JSON.stringify(options);
  391. }
  392. }
  393. window.addEventListener("beforeunload", wmepn_saveLandmarkNamesOptions, false);
  394.  
  395. // begin periodic updates
  396. //window.setInterval(wmepn_showLandmarkNames,500);
  397.  
  398. // trigger code when page is fully loaded, to catch any missing bits
  399. window.addEventListener("load", function(e) {
  400. var mapProblems = wmepn_getId('map-problems-explanation')
  401. if (mapProblems !== null) mapProblems.style.display = "none";
  402. });
  403.  
  404. // register some events...
  405. map.events.register("zoomend", null, wmepn_showLandmarkNames);
  406. map.events.register("changelayer", null, wmepn_showLandmarkNames);
  407. map.events.register("mouseout", null, wmepn_showLandmarkNames);
  408. Waze.selectionManager.events.register("selectionchanged", null, wmepn_showLandmarkNames);
  409. }
  410.  
  411. /* engage! =================================================================== */
  412. bootstrapLandmarkNames();
  413.  
  414. /* end ======================================================================= */

QingJ © 2025

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