WME Form Filler

Use info from WME to automatically fill out related forms

当前为 2018-09-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WME Form Filler
  3. // @description Use info from WME to automatically fill out related forms
  4. // @namespace https://greasyfork.org/users/6605
  5. // @version 1.4.4.2
  6. // @homepage https://github.com/WazeDev/WME-Form-Filler
  7. // @supportURL https://github.com/WazeDev/WME-Form-Filler/issues
  8. // @include https://www.waze.com/editor
  9. // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/
  10. // @author crazycaveman
  11. // @license MIT
  12. // @run-at document-end
  13. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUIzRDdFNzAwRTlGMTFFNkIyRDZGMzNERUFDMUM1NDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUIzRDdFNzEwRTlGMTFFNkIyRDZGMzNERUFDMUM1NDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1QjNEN0U2RTBFOUYxMUU2QjJENkYzM0RFQUMxQzU0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1QjNEN0U2RjBFOUYxMUU2QjJENkYzM0RFQUMxQzU0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtdrqLIAAAOCSURBVHjatJdLaBNBGMdn81ITQ2mLNqlIKInGkpSgFooPpKGHIlZPJqgoIvQivooPfFUsxYNVW62KiuItPah48RaUSlFEaDzEqgeV+sBUxag1rZa8Nv6nfMKaZpNssx34kdnN7sx/5nvNCtFolAUCAW8ymdwtCIKZMZZh6jQBjIIL4EkikWA+n485HI7/HtLFYjHH0NDQnXQ6XQkBbAbaGrAsHo+PNDc3T/lTF4lEVouiWKnX62O4DgBRpYn1YBuoAkuxwBGNRjNVAP7QZjKTu/4V7FJ59euAEWjlHtBg2//ZXEOq1WpzaUyWz690Ms5jUDhZcrqm0+UYyAPuKxyH2zqohgC++j/gmcJxRot5yGAwFBTAr9+AtWrHIqKMBYNBFgqFmlKpVLympuax1+udIiBD9reUON/nLMcTtFotC4fDBoR8H5JSVV1dXVdjY+OxbAEpUA8GSxRQC95KrkUe6jABzwnbkQ/OmUwmPSJQzBbAw+YL6C5hcr7y72TO2TTeI9AA7oErELNBp9NF5HzgEziogtnNZM6j4BfoAfNBB0XZu1wCuAkWggMKJ7sBXmbd4xmwH1wHW8FKut/Hi5NcFIiUu/cpFNCfQ0ACHKGdOM0LHbx/DE54HJWX92XDMEy7oKRFc9z7SXSBBZiYWSyWs0aj8QMvzVarVTYRJckP1GhLwN7J7Ugkhv1+f4/H48mbiPi+LOKeWmIUtIKP4AxFAiNn/F0oE/KX5wB3iQLSoAmsp3sPwW0q+3kF8HL8HFgVTqrJqvn8upf6XMyhYotRhsKnVqEAXj9ikuv9wEX9m/mKWy4fWA6eKhSwEdylfjVop/4PcEJJOebbOAz2KDgdC1kr7ATl1O+gUFwMXhcjgNvuG7g8TQdcAXZQ/xW4RLvxXk6ARmagBhqoTHJvFdhCUSLX2iVjttH7h8GEEh9wggEwiw4mfirRA2Sia2CnzHjV9HuLCs5FOpwmlERBGU3Om41+50nCzJ4nFCM0eTftlI/XAJ778WHCeDou5kg2SNtXLzkXPAAnKbWeymOCzWCM+nwRGT55S0sLs9lszG635xQgSCphivq9OU7LnQUcUJRMzts4T0JozOl0Ci6Xq6AJ+GHhPGUuNRo/jJRTGZbPAyiLIZzRJrBVZXi4bQY+TsfNZvMLWQEVFRVht9u9CQJaIcCk8uf5GArQVRxAh+Ue+ivAAAY7DIf3WTuXAAAAAElFTkSuQmCC
  14. // @grant none
  15. // ==/UserScript==
  16.  
  17. /*global W, $, GM_info */
  18.  
  19. (function () {
  20. "use strict";
  21. var WMEFFName = GM_info.script.name;
  22. var WMEFFVersion = GM_info.script.version;
  23. var WMEFFIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUIzRDdFNzAwRTlGMTFFNkIyRDZGMzNERUFDMUM1NDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUIzRDdFNzEwRTlGMTFFNkIyRDZGMzNERUFDMUM1NDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1QjNEN0U2RTBFOUYxMUU2QjJENkYzM0RFQUMxQzU0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1QjNEN0U2RjBFOUYxMUU2QjJENkYzM0RFQUMxQzU0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtdrqLIAAAOCSURBVHjatJdLaBNBGMdn81ITQ2mLNqlIKInGkpSgFooPpKGHIlZPJqgoIvQivooPfFUsxYNVW62KiuItPah48RaUSlFEaDzEqgeV+sBUxag1rZa8Nv6nfMKaZpNssx34kdnN7sx/5nvNCtFolAUCAW8ymdwtCIKZMZZh6jQBjIIL4EkikWA+n485HI7/HtLFYjHH0NDQnXQ6XQkBbAbaGrAsHo+PNDc3T/lTF4lEVouiWKnX62O4DgBRpYn1YBuoAkuxwBGNRjNVAP7QZjKTu/4V7FJ59euAEWjlHtBg2//ZXEOq1WpzaUyWz690Ms5jUDhZcrqm0+UYyAPuKxyH2zqohgC++j/gmcJxRot5yGAwFBTAr9+AtWrHIqKMBYNBFgqFmlKpVLympuax1+udIiBD9reUON/nLMcTtFotC4fDBoR8H5JSVV1dXVdjY+OxbAEpUA8GSxRQC95KrkUe6jABzwnbkQ/OmUwmPSJQzBbAw+YL6C5hcr7y72TO2TTeI9AA7oErELNBp9NF5HzgEziogtnNZM6j4BfoAfNBB0XZu1wCuAkWggMKJ7sBXmbd4xmwH1wHW8FKut/Hi5NcFIiUu/cpFNCfQ0ACHKGdOM0LHbx/DE54HJWX92XDMEy7oKRFc9z7SXSBBZiYWSyWs0aj8QMvzVarVTYRJckP1GhLwN7J7Ugkhv1+f4/H48mbiPi+LOKeWmIUtIKP4AxFAiNn/F0oE/KX5wB3iQLSoAmsp3sPwW0q+3kF8HL8HFgVTqrJqvn8upf6XMyhYotRhsKnVqEAXj9ikuv9wEX9m/mKWy4fWA6eKhSwEdylfjVop/4PcEJJOebbOAz2KDgdC1kr7ATl1O+gUFwMXhcjgNvuG7g8TQdcAXZQ/xW4RLvxXk6ARmagBhqoTHJvFdhCUSLX2iVjttH7h8GEEh9wggEwiw4mfirRA2Sia2CnzHjV9HuLCs5FOpwmlERBGU3Om41+50nCzJ4nFCM0eTftlI/XAJ778WHCeDou5kg2SNtXLzkXPAAnKbWeymOCzWCM+nwRGT55S0sLs9lszG635xQgSCphivq9OU7LnQUcUJRMzts4T0JozOl0Ci6Xq6AJ+GHhPGUuNRo/jJRTGZbPAyiLIZzRJrBVZXi4bQY+TsfNZvMLWQEVFRVht9u9CQJaIcCk8uf5GArQVRxAh+Ue+ivAAAY7DIf3WTuXAAAAAElFTkSuQmCC";
  24. var forms = [];
  25.  
  26. function formfiller_bootstrap() {
  27. formfiller_log("Running bootstrap");
  28.  
  29. if (typeof W.app === "undefined" || !window.W.map) {
  30. setTimeout(formfiller_bootstrap, 500);
  31. return;
  32. }
  33. formfiller_log("Starting init");
  34. formfiller_init();
  35. }
  36.  
  37. function formfiller_init() {
  38. // Check document elements are ready
  39. var userInfo = document.getElementById("user-info");
  40. if (userInfo === null) {
  41. window.setTimeout(formfiller_init, 500);
  42. return;
  43. }
  44. var userTabs = document.getElementById("user-tabs");
  45. if (userTabs === null) {
  46. window.setTimeout(formfiller_init, 500);
  47. return;
  48. }
  49. var navTab = userInfo.getElementsByTagName("ul");
  50. if (navTab.length === 0) {
  51. window.setTimeout(formfiller_init, 500);
  52. return;
  53. }
  54. if (typeof navTab[0] === "undefined") {
  55. window.setTimeout(formfiller_init, 500);
  56. return;
  57. }
  58. var tabContent = userInfo.getElementsByTagName("div");
  59. if (tabContent.length === 0) {
  60. window.setTimeout(formfiller_init, 500);
  61. return;
  62. }
  63. if (typeof tabContent[0] === "undefined") {
  64. window.setTimeout(formfiller_init, 500);
  65. return;
  66. }
  67.  
  68. ff_addUserTab();
  69. ff_addFormBtn();
  70. var formFillerObserver = new MutationObserver(function (mutations) {
  71. mutations.forEach(function (mutation) {
  72. // Mutation is a NodeList and doesn't support forEach like an array
  73. for (var i = 0; i < mutation.addedNodes.length; i += 1) {
  74. var addedNode = mutation.addedNodes[i];
  75.  
  76. // Only fire up if it's a node
  77. if (addedNode.nodeType === Node.ELEMENT_NODE) {
  78. var selectionDiv = addedNode.querySelector("div.selection");
  79.  
  80. if (selectionDiv) {
  81. ff_addFormBtn();
  82. }
  83. }
  84. }
  85. });
  86. });
  87. formFillerObserver.observe(document.getElementById("edit-panel"), {
  88. childList: true,
  89. subtree: true
  90. });
  91. //W.selectionManager.events.register("selectionchanged", null, ff_addFormBtn);
  92. if (W.app.modeController) {
  93. W.app.modeController.model.bind("change:mode", function (model, modeId) {
  94. if (modeId === 0) {
  95. ff_addUserTab();
  96. }
  97. });
  98. }
  99.  
  100. // Unit switched (imperial/metric)
  101. if (W.prefs) {
  102. W.prefs.on("change:isImperial", ff_addUserTab);
  103. }
  104.  
  105. if (!W.selectionManager.getSelectedFeatures) {
  106. W.selectionManager.getSelectedFeatures = W.selectionManager.getSelectedItems;
  107. }
  108. formfiller_log("Init done");
  109. return;
  110. }
  111.  
  112. //Shamelessly copied from https://gist.github.com/CalebGrove/c285a9510948b633aa47
  113. function abbrState(input, to) {
  114. var states = [
  115. ["ALABAMA", "AL"],
  116. ["ALASKA", "AK"],
  117. ["ARIZONA", "AZ"],
  118. ["ARKANSAS", "AR"],
  119. ["CALIFORNIA", "CA"],
  120. ["COLORADO", "CO"],
  121. ["CONNECTICUT", "CT"],
  122. ["DELAWARE", "DE"],
  123. ["DISTRICT OF COLUMBIA", "DC"],
  124. ["FLORIDA", "FL"],
  125. ["GEORGIA", "GA"],
  126. ["HAWAII", "HI"],
  127. ["IDAHO", "ID"],
  128. ["ILLINOIS", "IL"],
  129. ["INDIANA", "IN"],
  130. ["IOWA", "IA"],
  131. ["KANSAS", "KS"],
  132. ["KENTUCKY", "KY"],
  133. ["LOUISIANA", "LA"],
  134. ["MAINE", "ME"],
  135. ["MARYLAND", "MD"],
  136. ["MASSACHUSETTS", "MA"],
  137. ["MICHIGAN", "MI"],
  138. ["MINNESOTA", "MN"],
  139. ["MISSISSIPPI", "MS"],
  140. ["MISSOURI", "MO"],
  141. ["MONTANA", "MT"],
  142. ["NEBRASKA", "NE"],
  143. ["NEVADA", "NV"],
  144. ["NEW HAMPSHIRE", "NH"],
  145. ["NEW JERSEY", "NJ"],
  146. ["NEW MEXICO", "NM"],
  147. ["NEW YORK", "NY"],
  148. ["NORTH CAROLINA", "NC"],
  149. ["NORTH DAKOTA", "ND"],
  150. ["OHIO", "OH"],
  151. ["OKLAHOMA", "OK"],
  152. ["OREGON", "OR"],
  153. ["PENNSYLVANIA", "PA"],
  154. ["RHODE ISLAND", "RI"],
  155. ["SOUTH CAROLINA", "SC"],
  156. ["SOUTH DAKOTA", "SD"],
  157. ["TENNESSEE", "TN"],
  158. ["TEXAS", "TX"],
  159. ["UTAH", "UT"],
  160. ["VERMONT", "VT"],
  161. ["VIRGINIA", "VA"],
  162. ["WASHINGTON", "WA"],
  163. ["WEST VIRGINIA", "WV"],
  164. ["WISCONSIN", "WI"],
  165. ["WYOMING", "WY"],
  166. ["PUERTO RICO", "PR"],
  167. ["VIRGIN ISLANDS (U.S.)", "VI"]
  168. ];
  169.  
  170. var i;
  171. if (to === "abbr") {
  172. input = input.toUpperCase();
  173. for (i = 0; i < states.length; i += 1) {
  174. if (states[i][0] === input) {
  175. return (states[i][1]);
  176. }
  177. }
  178. } else if (to === "name") {
  179. input = input.toUpperCase();
  180. for (i = 0; i < states.length; i += 1) {
  181. if (states[i][1] === input) {
  182. return (states[i][0]);
  183. }
  184. }
  185. }
  186. }
  187.  
  188. function formfiller_log(message) {
  189. if (typeof message === "string") {
  190. console.log("FormFiller: " + message);
  191. } else {
  192. console.log("FormFiller: ", message);
  193. }
  194. }
  195.  
  196. function ff_getStreetName(selection) {
  197. var streetName = "",
  198. i;
  199.  
  200. for (i = 0; i < selection.length; i += 1) {
  201. var newStreet = W.model.streets.getObjectById(selection[i].model.attributes.primaryStreetID);
  202. if (typeof newStreet === "undefined" || newStreet.name === null) {
  203. newStreet = "No Name";
  204. }
  205. if (streetName === "") {
  206. streetName = newStreet.name;
  207. } else if (streetName !== newStreet.name) {
  208. streetName += ", " + newStreet.name;
  209. }
  210. }
  211. return streetName;
  212. }
  213.  
  214. function ff_getState(selection) {
  215. var stateName = "",
  216. i;
  217.  
  218. for (i = 0; i < selection.length; i += 1) {
  219. var cID = W.model.streets.getObjectById(selection[i].model.attributes.primaryStreetID).cityID;
  220. var sID = W.model.cities.getObjectById(cID).attributes.stateID;
  221. var newState = W.model.states.getObjectById(sID).name;
  222.  
  223. if (newState === "") {
  224. sID = W.model.cities.getObjectById(cID).attributes.countryID;
  225. newState = W.model.countries.getObjectById(sID).name;
  226. formfiller_log("cID: " + cID);
  227. formfiller_log("sID: " + sID);
  228. formfiller_log("newState: " + newState);
  229. }
  230.  
  231. if (stateName === "") {
  232. stateName = newState;
  233. } else if (stateName !== newState) {
  234. stateName = "";
  235. break;
  236. }
  237. }
  238. return stateName;
  239. }
  240.  
  241. function ff_getCity(selection) {
  242. var cityName = "",
  243. i;
  244. for (i = 0; i < selection.length; i += 1) {
  245. var cID = W.model.streets.getObjectById(selection[i].model.attributes.primaryStreetID).cityID;
  246. var newCity = W.model.cities.getObjectById(cID).attributes.name;
  247. if (cityName === "") {
  248. cityName = newCity;
  249. } else if (cityName !== newCity) {
  250. cityName = "";
  251. break;
  252. }
  253. }
  254. return cityName;
  255. }
  256.  
  257. function ff_getCounty(selection) {
  258. var county = "";
  259. var center = W.map.center.clone().transform(W.map.projection.projCode, W.map.displayProjection.projCode);
  260. //formfiller_log("Getting county for "+center.lat.toString()+","+center.lon.toString());
  261. var xhr = new XMLHttpRequest();
  262. xhr.open("GET", "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + center.lat + "," + center.lon, false);
  263. xhr.onload = function () {
  264. if (xhr.readyState === 4) {
  265. if (xhr.status === 200) {
  266. var response = JSON.parse(xhr.responseText);
  267. if (response.status !== "OK") {
  268. formfiller_log(`Error getting county name (${response.status})`);
  269. return county;
  270. }
  271. var addrComps = response.results[0].address_components;
  272. var comp;
  273. for (comp = 0; comp < addrComps.length; comp += 1) {
  274. if (addrComps[comp].types.indexOf("administrative_area_level_2") !== -1) {
  275. county = addrComps[comp].long_name;
  276. //formfiller_log("ff_getCounty: "+county);
  277. var countyIndex = (county.indexOf(" County") !== -1 ? county.indexOf(" County") : county.indexOf(" Parish"));
  278. if (countyIndex !== -1) {
  279. county = county.slice(0, countyIndex);
  280. }
  281. break;
  282. }
  283. }
  284. }
  285. }
  286. };
  287. xhr.send(null);
  288. return county;
  289.  
  290. //Async call. Figure this out!
  291. /*return $.getJSON("https://maps.googleapis.com/maps/api/geocode/json?latlng="+center.lat+","+center.lon, function(data) {
  292. if (data.status === "OK")
  293. {
  294. var addrComps = data.results[0].address_components;
  295. for (comp = 0; comp < addrComps.length; comp+=1)
  296. {
  297. if (addrComps[comp].types.indexOf("administrative_area_level_2") !== -1)
  298. {
  299. county = addrComps[comp].long_name;
  300. county = county.slice(0,county.indexOf(" County"));
  301. formfiller_log("JSON func "+county);
  302. break;
  303. }
  304. }
  305. }
  306. if (county === "")
  307. county = "Not found";
  308. formfiller_log("Got county");
  309. formfiller_log(county);
  310. return county;
  311. });*/
  312. }
  313.  
  314. function ff_closureActive(selection) {
  315. var i;
  316. for (i = 0; i < selection.length; i += 1) {
  317. if (selection[i].model.hasClosures()) {
  318. if (W.model.roadClosures.getByAttributes({
  319. segID: selection[i].model.attributes.id
  320. })[0].active) {
  321. return true;
  322. }
  323. }
  324. }
  325. return false;
  326. }
  327.  
  328. function ff_getClosureInfo(seg) {
  329. var closureInfo = {
  330. closedDir: "",
  331. endDate: "",
  332. idFwd: "",
  333. idRev: "",
  334. closedReason: ""
  335. };
  336. var segID = seg.model.attributes.id;
  337. var closureList = W.model.roadClosures.getByAttributes({
  338. segID: segID,
  339. active: true
  340. });
  341. var i;
  342.  
  343. for (i = 0; i < closureList.length; i += 1) {
  344. if (closureList[i].active === true) {
  345. if (closureInfo.endDate === "") {
  346. closureInfo.endDate = closureList[i].endDate;
  347. } else if (closureInfo.endDate > closureList[i].endDate) {
  348. closureInfo.endDate = closureList[i].endDate;
  349. }
  350. if (closureList[i].forward === true) {
  351. closureInfo.idFwd = closureList[i].id;
  352. } else {
  353. closureInfo.idRev = closureList[i].id;
  354. }
  355. if (closureInfo.closedReason === "") {
  356. closureInfo.closedReason = closureList[i].closedReason;
  357. }
  358. }
  359. }
  360.  
  361. if (closureInfo.idFwd !== "" && closureInfo.idRev !== "") {
  362. closureInfo.closedDir = "Two-Way";
  363. } else {
  364. closureInfo.closedDir = "One-Way";
  365. }
  366.  
  367. return closureInfo;
  368. }
  369.  
  370. function ff_createPermalink(selection) {
  371. //https://www.waze.com/editor/?env=usa&lon=-79.79248&lat=32.86150&layers=12709&zoom=5&mode=0&mapProblemFilter=1&mapUpdateRequestFilter=0&venueFilter=0&segments=504534141
  372. //https://www.waze.com/editor/?env=usa&lon=-79.79248&lat=32.86150&layers=12709&zoom=5&mode=0&mapProblemFilter=1&mapUpdateRequestFilter=0&venueFilter=0&venues=183632201.1836387542.3102948
  373. var permalink = "https://www.waze.com/editor/?",
  374. segIDs = [];
  375. var latLon = W.map.center.clone().transform(W.map.projection.projCode, W.map.displayProjection.projCode);
  376. var lat = latLon.lat,
  377. lon = latLon.lon;
  378. var env = W.location ? W.location.code : W.app.getAppRegionCode();
  379. var type = "segments";
  380. var zoom = W.map.zoom;
  381. var zoomToRoadType = W.Config.segments.zoomToRoadType;
  382. var i;
  383.  
  384. //To get lat and long centered on segment
  385. if (selection.length === 1) {
  386. latLon = selection[0].model.getCenter().clone();
  387. latLon.transform(W.map.projection.projCode, W.map.displayProjection.projCode);
  388. lat = latLon.y;
  389. lon = latLon.x;
  390. }
  391.  
  392. for (i = 0; i < selection.length; i += 1) {
  393. var segment = selection[i].model;
  394. if (segment.type === "segment") {
  395. segIDs.push(segment.attributes.id);
  396. if (zoomToRoadType[zoom] !== -1 && zoomToRoadType[zoom].indexOf(segment.attributes.roadType) === -1) {
  397. alert("This zoom level (" + zoom.toString() + ") cannot be used for this road type! Please increase your zoom:\n" +
  398. "Streets: 4+\nOther drivable and Non-drivable: 3+\nHighways and PS: 2+");
  399. formfiller_log("Zoom level not correct for segment: " + zoom.toString() + " " + segment.attributes.roadType.toString());
  400. return;
  401. }
  402. }
  403. }
  404. permalink += "env=" + env + "&lon=" + lon + "&lat=" + lat + "&zoom=" + zoom.toString() + "&" + type + "=" + segIDs.join();
  405. return permalink;
  406. }
  407.  
  408. function ff_getLastEditor(selection) {
  409. var eID;
  410. var editorNames = "";
  411. var newEdName = "";
  412. //selection[0].model.attributes.updatedBy;
  413. selection.forEach(function (selected) {
  414. eID = selected.model.attributes.updatedBy;
  415. if (typeof eID !== "undefined") {
  416. formfiller_log("Unable to get updatedBy on " + selected.model.attributes.id);
  417. eID = selected.model.attributes.createdBy;
  418. }
  419. newEdName = W.model.users.getObjectById(eID).userName;
  420. if (editorNames.indexOf(newEdName) === -1) {
  421. editorNames += ", " + newEdName;
  422. }
  423.  
  424. });
  425. editorNames = editorNames.substr(2);
  426. return editorNames;
  427. }
  428.  
  429. function ff_createFormLink(formSel) {
  430. var selection = W.selectionManager.getSelectedFeatures();
  431. var formValues = {};
  432. var formFields = formSel.fields;
  433. var formLink = formSel.url + "?entry.";
  434. var formArgs = [];
  435. if (selection.length === 0 || selection[0].model.type !== "segment") {
  436. formfiller_log("No segments selected.");
  437. return;
  438. }
  439.  
  440. /*Fields expected:
  441. username
  442. permalink
  443. closedDir
  444. closureStatus
  445. closedReason
  446. endDate
  447. streetname
  448. fromStreet
  449. toStreet
  450. stateabbr
  451. county
  452. city
  453. source
  454. notes
  455. */
  456.  
  457. Object.keys(formFields).forEach(function (key, index) {
  458. switch (key) {
  459. case "username":
  460. formValues[key] = W.loginManager.user.userName;
  461. break;
  462. case "permalink":
  463. formValues[key] = ff_createPermalink(selection);
  464. if (typeof formValues.permalink === "undefined") {
  465. formfiller_log("No permalink generated");
  466. return;
  467. }
  468. break;
  469. case "streetname":
  470. formValues[key] = ff_getStreetName(selection);
  471. break;
  472. case "editorName":
  473. formValues[key] = ff_getLastEditor(selection);
  474. break;
  475. case "stateabbr":
  476. formValues[key] = abbrState(ff_getState(selection), "abbr");
  477. break;
  478. case "state":
  479. formValues[key] = ff_getState(selection);
  480. break;
  481. case "county":
  482. formValues.county = ff_getCounty(selection);
  483. break;
  484. case "city":
  485. formValues[key] = ff_getCity(selection);
  486. break;
  487. case "notes":
  488. formValues[key] = "Form filled by " + WMEFFName + " v" + WMEFFVersion;
  489. break;
  490. case "closureStatus":
  491. if (selection[0].model.type === "segment") {
  492. if (ff_closureActive(selection)) {
  493. formValues.closureStatus = "CLOSED";
  494. var closureInfo = ff_getClosureInfo(selection[0]);
  495. formValues.closedDir = closureInfo.closedDir;
  496. formValues.closedReason = closureInfo.closedReason;
  497. formValues.endDate = closureInfo.endDate;
  498. } else {
  499. formValues.closureStatus = "REPORTED";
  500. formValues.closedDir = "Two-Way";
  501. formValues.closedReason = document.getElementById("ff-closure-reason").value;
  502. formValues.endDate = document.getElementById("ff-closure-endDate").value + "+" + document.getElementById("ff-closure-endTime").value;
  503. }
  504. }
  505. break;
  506. default:
  507. formfiller_log("Nothing defined for " + key);
  508. break;
  509. }
  510.  
  511. //Add entry to form URL, if there's something to add
  512. if (typeof formValues[key] !== "undefined" && formValues[key] !== "") {
  513. formArgs[index] = formFields[key] + "=" + encodeURIComponent(formValues[key]);
  514. }
  515. });
  516. formLink += formArgs.join("&entry.");
  517.  
  518. formfiller_log(formLink);
  519. return formLink;
  520. }
  521.  
  522. function ff_addFormBtn() {
  523. var selection = W.selectionManager.getSelectedFeatures();
  524. var ffDiv = document.createElement("div"),
  525. ffMnu = document.createElement("select"),
  526. ffBtn = document.createElement("button");
  527. var formWindowName = "WME Form Filler result",
  528. formWindowSpecs = "resizable=1,menubar=0,scrollbars=1,status=0,toolbar=0";
  529. var editPanel,
  530. selElem,
  531. formLink;
  532. ffDiv.id = "formfillerDiv";
  533. editPanel = document.getElementById("edit-panel");
  534. selElem = editPanel.getElementsByClassName("selection");
  535. if (selection.length === 0 || selection[0].model.type !== "segment") {
  536. //formfiller_log("No segments selected.");
  537. return;
  538. }
  539. if (document.getElementById("formfillerDiv")) {
  540. //formfiller_log("Div already created");
  541. return;
  542. }
  543.  
  544. forms = [{
  545. //https://docs.google.com/forms/d/e/1FAIpQLSduBiLMhbg6nRpsEVCTcVbV4eWmHDXdIKGtuaOvzy6NZLbSgw/viewform?entry.1553765347=username&entry.1264424583=CLOSED&entry.1811077109=permalink&entry.792657790=Two-Way&entry.345142186=reason&entry.1102521735=2016-09-20+03:00&entry.2015424420=street+name&entry.1547375393=from+street&entry.1335391716=to+street&entry.1867193205=SC&entry.1714138473=county&entry.1803937317=source&entry.1648634142=notes
  546. name: "USA VEOC closures",
  547. url: "https://docs.google.com/forms/d/e/1FAIpQLSduBiLMhbg6nRpsEVCTcVbV4eWmHDXdIKGtuaOvzy6NZLbSgw/viewform",
  548. fields: {
  549. username: "1553765347",
  550. closureStatus: "1264424583",
  551. permalink: "1811077109",
  552. closedDir: "792657790",
  553. closedReason: "345142186",
  554. endDate: "1102521735",
  555. streetname: "2015424420",
  556. fromStreet: "1547375393",
  557. toStreet: "1335391716",
  558. stateabbr: "1867193205",
  559. county: "1714138473",
  560. source: "1803937317",
  561. notes: "1648634142"
  562. }
  563. }, {
  564. name: "US Jane TTS Pronunciation",
  565. url: "https://docs.google.com/forms/d/e/1FAIpQLSeuCmC0zy7GEQDJQP5R8dndxYhXCkqzadrPgP89BvatVl1bdg/viewform",
  566. fields: {
  567. username: "324217272",
  568. state: "1065619417",
  569. issue: "1086951221",
  570. streetname: "1163516948",
  571. incorrectp: "1191620241",
  572. correctp: "1649051316",
  573. permalink: "2028167849",
  574. instructions: "2120232339",
  575. comments: "1917392591"
  576. }
  577. }, {
  578. //https://docs.google.com/forms/d/e/1FAIpQLSff7nsBw8qxCojBdxrjTPl6tercqyyzGy92Vif_SBdHkYDchw/viewform?entry.1204781462=Reporter&entry.828228572=Reported&entry.1647952662=Street+name+&entry.1501712688=From+street+&entry.2094306654=To+street+&entry.1414240321=Two-Way&entry.900957975=10/27/2016+00:00&entry.1051351191=Adams&entry.1093044522=City+&entry.1540676081=IDOT&entry.430378754=Reason+&entry.1754051160=Permalink+&entry.172235277=Source+&entry.1722909714=Notes+
  579. name: "IL closures",
  580. url: "https://docs.google.com/forms/d/e/1FAIpQLSff7nsBw8qxCojBdxrjTPl6tercqyyzGy92Vif_SBdHkYDchw/viewform",
  581. fields: {
  582. username: "1204781462",
  583. closureStatus: "828228572",
  584. permalink: "1754051160",
  585. closedDir: "1414240321",
  586. closedReason: "430378754",
  587. endDate: "900957975",
  588. streetname: "1647952662",
  589. fromStreet: "1501712688",
  590. toStreet: "2094306654",
  591. county: "1051351191",
  592. city: "1093044522",
  593. source: "172235277",
  594. notes: "1722909714"
  595. }
  596. }, {
  597. //https://docs.google.com/forms/d/e/1FAIpQLScwEyNVqiHHdFjc4hr82zlFXW2bAsff9pqIzFUqT8Evh6YROg/viewform?usp=pp_url&entry.1553765347=kwrigh01&entry.1264424583=CLOSED&entry.1811077109=https://www.waze.com/editor/?env%3Dusa%26lon%3D-79.99979%26lat%3D37.89567%26zoom%3D5%26segments%3D82457306,82457308,82457338&entry.792657790=Two-Way&entry.345142186=Bridge+Work&entry.1102521735=2018-07-01+23:59&entry.2015424420=Morris+Hollow+Rd&entry.1547375393=1st&entry.1335391716=2nd&entry.1867193205=VA&entry.1714138473=Alleghany&entry.1803937317=VDOT&entry.1648634142=Test+Closure
  598. name: "VA Closures",
  599. url: "https://docs.google.com/forms/d/e/1FAIpQLScwEyNVqiHHdFjc4hr82zlFXW2bAsff9pqIzFUqT8Evh6YROg/viewform",
  600. fields: {
  601. username: "1553765347",
  602. closureStatus: "1264424583",
  603. permalink: "1811077109",
  604. closedDir: "792657790",
  605. closedReason: "345142186",
  606. endDate: "1102521735",
  607. streetname: "2015424420",
  608. fromStreet: "1547375393",
  609. toStreet: "1335391716",
  610. stateabbr: "1867193205",
  611. county: "1714138473",
  612. source: "1803937317",
  613. notes: "1648634142"
  614. }
  615. }, {
  616. //https://docs.google.com/forms/d/e/1FAIpQLSeiKY0KsO0xN69Asw77MARQFmxOy6zQXF-k2OQdWOfwtiCp7Q/viewform?entry.1204781462=ojlaw&entry.828228572=CLOSED&entry.1647952662=Test1&entry.1501712688=Test2&entry.2094306654=Test3&entry.1414240321=One-Way&entry.900957975=00/00/0000+00:00&entry.1051351191=Adams&entry.1093044522=Test4&entry.1540676081=City&entry.430378754=Test5&entry.1754051160=Test6&entry.172235277=Test7&entry.1722909714=Test8
  617. name: "WI closures",
  618. url: "https://docs.google.com/forms/d/e/1FAIpQLSeiKY0KsO0xN69Asw77MARQFmxOy6zQXF-k2OQdWOfwtiCp7Q/viewform",
  619. fields: {
  620. username: "1204781462",
  621. closureStatus: "828228572",
  622. permalink: "1754051160",
  623. closedDir: "1414240321",
  624. closedReason: "430378754",
  625. endDate: "900957975",
  626. streetname: "1647952662",
  627. fromStreet: "1501712688",
  628. toStreet: "2094306654",
  629. county: "1051351191",
  630. city: "1093044522",
  631. source: "172235277",
  632. notes: "1722909714"
  633. }
  634. }, {
  635. //https://docs.google.com/forms/d/e/1FAIpQLSf3YAdjscVvJXiU4KWq0e8J8XyCyYBDyharRoXW3bf6R4wH1w/viewform?usp=pp_url&entry.1553765347=kwrigh01&entry.1264424583=CLOSED&entry.1811077109=https://www.waze.com/editor/?env%3Dusa%26lon%3D-80.26934%26lat%3D39.39069%26zoom%3D5%26segments%3D504613052,55526394,55530967&entry.792657790=Two-Way&entry.345142186=Road+Slip&entry.1102521735=2018-06-01+16:00&entry.2015424420=Janes+Hill+Rd&entry.1547375393&entry.1335391716&entry.1714138473=Harrison+&entry.1803937317=WVDOT+&entry.1648634142=Closed+Indefinitely
  636. name: "WV Closures",
  637. url: "https://docs.google.com/forms/d/e/1FAIpQLSf3YAdjscVvJXiU4KWq0e8J8XyCyYBDyharRoXW3bf6R4wH1w/viewform",
  638. fields: {
  639. username: "1553765347",
  640. closureStatus: "1264424583",
  641. permalink: "1811077109",
  642. closedDir: "792657790",
  643. closedReason: "345142186",
  644. endDate: "1102521735",
  645. streetname: "2015424420",
  646. fromStreet: "1547375393",
  647. toStreet: "1335391716",
  648. county: "1714138473",
  649. source: "1803937317",
  650. notes: "1648634142"
  651. }
  652. }
  653. /*{
  654. //https://docs.google.com/forms/d/e/1FAIpQLScY_5WKyYTqvH1fdiBThqLO4DRIzFzgdBtBexw5-iKL_LOzBw/viewform?entry.1553765347=username&entry.1264424583=CLOSED&entry.1811077109=permalink&entry.792657790=Two-Way&entry.345142186=reason&entry.1102521735=2016-09-20+03:00&entry.2015424420=street+name&entry.1547375393=from+street&entry.1335391716=to+street&entry.1867193205=SC&entry.1714138473=county&entry.1803937317=source&entry.1648634142=notes
  655. name: "USA Weather related closures",
  656. url: "https://docs.google.com/forms/d/e/1FAIpQLScY_5WKyYTqvH1fdiBThqLO4DRIzFzgdBtBexw5-iKL_LOzBw/viewform",
  657. username: "1553765347",
  658. closureStatus: "1264424583",
  659. permalink: "1811077109",
  660. closedDir: "792657790",
  661. closedReason: "345142186",
  662. endDate: "1102521735",
  663. streetname: "2015424420",
  664. fromStreet: "1547375393",
  665. toStreet: "1335391716",
  666. state: "1867193205",
  667. county: "1714138473",
  668. source: "1803937317",
  669. notes: "1648634142",
  670. }*/
  671. ];
  672.  
  673. forms.forEach(function (key, i) {
  674. ffMnu.options.add(new Option(forms[i].name, i));
  675. });
  676. ffBtn.innerHTML = "Go to Form";
  677. ffBtn.onclick = function () {
  678. //alert(ffMnu.options[ffMnu.selectedIndex].value+": "+forms[ffMnu.options[ffMnu.selectedIndex].value].name);
  679. ff_saveSettings();
  680. formLink = ff_createFormLink(forms[ffMnu.options[ffMnu.selectedIndex].value]);
  681. if (typeof formLink === "undefined") {
  682. return;
  683. }
  684.  
  685. if ($("#ff-open-in-tab").prop("checked")) {
  686. window.open(formLink, "_blank");
  687. } else {
  688. window.open(formLink, formWindowName, formWindowSpecs);
  689. }
  690. };
  691. ffDiv.appendChild(ffMnu);
  692. ffDiv.appendChild(ffBtn);
  693. selElem[0].appendChild(ffDiv);
  694.  
  695. return;
  696. }
  697.  
  698. function ff_loadSettings() {
  699. var todayDate = new Date(),
  700. futureDate = new Date(),
  701. daysInFuture = 3;
  702. var today = todayDate.getFullYear() + "-" + (todayDate.getMonth() + 1 < 10 ? "0" + (todayDate.getMonth() + 1) : todayDate.getMonth() + 1) + "-" + todayDate.getDate();
  703. futureDate.setDate(futureDate.getDate() + daysInFuture);
  704.  
  705. var ffOpenInTab = localStorage.getItem("ff-open-in-tab");
  706. if (ffOpenInTab === "1") {
  707. $("#ff-open-in-tab").trigger("click");
  708. }
  709. var ffClosureReason = localStorage.getItem("ff-closure-reason");
  710. if (ffClosureReason !== null) {
  711. $("#ff-closure-reason").val(ffClosureReason);
  712. }
  713. var ffClosureEndDate = localStorage.getItem("ff-closure-endDate");
  714. if (ffClosureEndDate !== null && ffClosureEndDate !== "" && ffClosureEndDate >= today) {
  715. $("#ff-closure-endDate").val(ffClosureEndDate);
  716. } else {
  717. var closureDate = futureDate.getFullYear() + "-" + (futureDate.getMonth() + 1 < 10 ? "0" + (futureDate.getMonth() + 1) : futureDate.getMonth() + 1) + "-" + (futureDate.getDate() < 10 ? "0" + futureDate.getDate() : futureDate.getDate());
  718. $("#ff-closure-endDate").val(closureDate);
  719. }
  720. var ffClosureEndTime = localStorage.getItem("ff-closure-endTime");
  721. if (ffClosureEndTime !== null && ffClosureEndTime !== "") {
  722. $("#ff-closure-endTime").val(ffClosureEndTime);
  723. }
  724. //formfiller_log("Settings loaded");
  725. return;
  726. }
  727.  
  728. function ff_saveSettings() {
  729. if ($("#ff-open-in-tab").prop("checked")) {
  730. localStorage.setItem("ff-open-in-tab", "1");
  731. } else {
  732. localStorage.setItem("ff-open-in-tab", "0");
  733. }
  734. localStorage.setItem("ff-closure-reason", $("#ff-closure-reason").val());
  735. localStorage.setItem("ff-closure-endDate", $("#ff-closure-endDate").val());
  736. localStorage.setItem("ff-closure-endTime", $("#ff-closure-endTime").val());
  737. //formfiller_log("Settings saved");
  738. return;
  739. }
  740.  
  741. function ff_addUserTab() {
  742. var userInfo = document.getElementById("user-info"),
  743. userTabs = document.getElementById("user-tabs"),
  744. navTabs = userTabs.getElementsByClassName("nav-tabs"),
  745. tabContent = userInfo.getElementsByClassName("tab-content");
  746. var ffTab = document.createElement("li"),
  747. ffPanel = document.createElement("div"),
  748. ffReason = document.createElement("div"),
  749. ffEndDate = document.createElement("div"),
  750. ffNewTabBox = document.createElement("input"),
  751. ffNewTabLabel = document.createElement("label"),
  752. ffTabInfo = document.createElement("div");
  753.  
  754. ffTab.innerHTML = '<a title="Form Filler" href="#sidepanel-formfill" data-toggle="tab"><img class="fa" src="' + WMEFFIcon + '" width="15px" /></a>';
  755. ffPanel.id = "sidepanel-formfill";
  756. ffPanel.className = "tab-pane";
  757.  
  758. ffTabInfo.innerHTML = '<b>' + WMEFFName + '</b> v' + WMEFFVersion;
  759.  
  760. ffNewTabBox.id = "ff-open-in-tab";
  761. ffNewTabBox.type = "checkbox";
  762. ffNewTabBox.name = "ff_open_tab";
  763.  
  764. ffNewTabLabel.innerHTML = "Open form in new tab";
  765. ffNewTabLabel.for = "ff_open_tab";
  766.  
  767. ffReason.className = "form-group";
  768. ffReason.innerHTML = '<label class="control-label" for="ff_closure_reason">Closures reason:</label><div class="controls"><input id="ff-closure-reason" class="form-control" type="text" name="ff_closure_reason"></div>';
  769.  
  770. ffEndDate.className = "form-group";
  771. ffEndDate.innerHTML = '<label class="control-label" for="ff_closure_endDate">Closures end:</label><div class="controls"><div class="date date-input-group input-group pull-left" style="width: 62%"><input id="ff-closure-endDate" class="form-control end-date" type="text" name="ff_closure_endDate"><span class="input-group-addon"><i class="fa fa-calendar"></i></span></div><div class="bootstrap-timepicker input-group style="width: 38%""><input id="ff-closure-endTime" class="end-time form-control" type="text" name="ff_closure_endTime"><span class="input-group-addon"><i class="fa fa-clock-o"></i></span></div></div>';
  772.  
  773. ffPanel.appendChild(ffTabInfo);
  774. ffPanel.appendChild(ffNewTabBox);
  775. ffPanel.appendChild(ffNewTabLabel);
  776. ffPanel.appendChild(ffReason);
  777. ffPanel.appendChild(ffEndDate);
  778. navTabs[0].appendChild(ffTab);
  779. tabContent[0].appendChild(ffPanel);
  780.  
  781. if (typeof $.fn.datepicker !== "undefined") {
  782. $("#ff-closure-endDate").datepicker({
  783. format: "yyyy-mm-dd",
  784. todayHighlight: true,
  785. autoclose: true
  786. });
  787. } else {
  788. if (typeof $.fn.daterangepicker !== "undefined") {
  789. $("#ff-closure-endDate").daterangepicker({
  790. singleDatePicker: true,
  791. locale: {
  792. format: "YYYY-MM-DD"
  793. }
  794. });
  795. }
  796. }
  797.  
  798. if (typeof $.fn.timepicker !== "undefined") {
  799. $("#ff-closure-endTime").timepicker({
  800. template: false,
  801. defaultTime: "00:00",
  802. showMeridian: false
  803. });
  804. }
  805.  
  806. ff_loadSettings();
  807. $("#ff-closure-reason").change(function () {
  808. ff_saveSettings();
  809. });
  810. $("#ff-closure-endDate").change(function () {
  811. ff_saveSettings();
  812. });
  813. $("#ff-closure-endTime").change(function () {
  814. ff_saveSettings();
  815. });
  816. $("#ff-open-in-tab").click(function () {
  817. ff_saveSettings();
  818. });
  819. }
  820.  
  821. setTimeout(formfiller_bootstrap, 2000);
  822. }());