WME LevelReset +

Fork of the original script. The WME LevelReset tool, to make re-locking segments and POI to their appropriate lock level easy & quick. Supports major road types and custom locking rules for specific cities.

当前为 2023-01-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WME LevelReset +
  3. // @namespace waze-ua
  4. // @version 2023.01.03.001
  5. // @description Fork of the original script. The WME LevelReset tool, to make re-locking segments and POI to their appropriate lock level easy & quick. Supports major road types and custom locking rules for specific cities.
  6. // @author Broos Gert '2015, madnut
  7. // @include https://*waze.com/*editor*
  8. // @exclude https://*waze.com/*user/editor*
  9. // @namespace https://greasyfork.org/ru/users/160654-waze-ukraine
  10. // @connect google.com
  11. // @connect script.googleusercontent.com
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM_addStyle
  14. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAA+VBMVEX///93PgHX19fTgQfFZgLLcwTrxYDDgA3nqBj5+fmwr6+Yl5f8/PzExMTl5eX114vv7+/e3t68vLzOzs6saRKARQSLTgeioqK2tbX72XfU1NT515fxz4b54b3RmySYWAv31aTpwIHgrn9/f3/75qPZsEvuuC/utx3psVP13KizbhXuuVj745bfoEzzwzDxwDXTjknpxqDPfhzWih7PhUaObErowqDJchrmqCfprRjbmUvblCLZjAv71WnhnyTfmA7hrmbjsm7qxpPv06vYljj305776MvLkD3XkjFwcHCMi4v6zk/6z1P2wVDYqzr3y3j2xWnrrl761X3u0VhGAAABv0lEQVQ4jZWTXXuaMBiGY7bZQUhIoBaKsIK0KkVqtd+2tJ2gnVJs9f//mAW78uHYwe6TXE+em/flJAD8D0RVdF3HTKqvGcaMAiAQVYd1vaEASikhhFKA1ZoeA8Iwct2lCAnAxl/zdcAMbeGipbtwMQM62xFEFUJtoWEIsbh0CVTF3QGqqrjax2cq4kkkFQFjTJD2eYeXBoa4uoEoBOU/RhBUWHWHJukUCZ9JQFCnWkVAQJRQniREyvGPANA/YzazRhBKwjSOg+DZmdoRZ+r8XAfxr5eo1AfzuW1HljXfYkX2zJ5b8TQXXtbWzPff38x2hvn27qf+zFrHubC39tppGoabjczZHIZpmra9/jgXTn2vnSTJaxgecsLwNRkmsueflgV5eLZarU4y+Lk6G9YIg8HxB4PBYEfY3woZQ0529rjQ3y+Evid3ez9K9LpmWTjqe2b3Ti5xlwlHhRDYzdvvFW5NOyiEAy48Pu2VeHps2sFBIUwi5/6hWeLh3okmhdCajJyLLxUunNGktS0lgdLW+agz/lZh3Bmdt6ggZS/NUBqX152brxVuOteXDZVRafsUrxq1XGHIBb6CwHoY4Tt+A1eiQ8S/AAv7AAAAAElFTkSuQmCC
  15. // ==/UserScript==
  16.  
  17. /* jshint esversion: 6 */
  18. /* global W */
  19. /* global $ */
  20. /* global require */
  21.  
  22. // initialize LevelReset and do some checks
  23. function LevelReset_bootstrap() {
  24. if (W && W.loginManager && W.loginManager.user && W.map && W.model && W.model.countries && W.model.countries.top) {
  25. console.log('LevelReset: Initializing...');
  26. LevelReset_init();
  27. } else {
  28. console.log('LevelReset: Bootstrap failed. Trying again...');
  29. setTimeout(LevelReset_bootstrap, 660);
  30. }
  31. }
  32.  
  33. function LevelReset_init() {
  34. // Setting up global variables
  35. const lrStyle = [
  36. '.tg { border-collapse: collapse; border-spacing: 0; margin: 0px auto; }',
  37. '.tg td { border-color: black; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 2px; word-break: normal; }',
  38. '.tg .tg-value { text-align: center; vertical-align: top }',
  39. '.tg .tg-header { background-color: #ecf4ff; border-color: #000000; font-weight: bold; text-align: center; vertical-align: top }',
  40. '.tg .tg-type { text-align: left; vertical-align: top }',
  41. ''];
  42. GM_addStyle(lrStyle.join('\n'));
  43.  
  44. const UpdateObject = require("Waze/Action/UpdateObject");
  45. const VERSION = GM_info.script.version;
  46. const loader = 'data:image/gif;base64,R0lGODlhEAAQAPQAAP///wAAAPj4+Dg4OISEhAYGBiYmJtbW1qioqBYWFnZ2dmZmZuTk5JiYmMbGxkhISFZWVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAAFUCAgjmRpnqUwFGwhKoRgqq2YFMaRGjWA8AbZiIBbjQQ8AmmFUJEQhQGJhaKOrCksgEla+KIkYvC6SJKQOISoNSYdeIk1ayA8ExTyeR3F749CACH5BAAKAAEALAAAAAAQABAAAAVoICCKR9KMaCoaxeCoqEAkRX3AwMHWxQIIjJSAZWgUEgzBwCBAEQpMwIDwY1FHgwJCtOW2UDWYIDyqNVVkUbYr6CK+o2eUMKgWrqKhj0FrEM8jQQALPFA3MAc8CQSAMA5ZBjgqDQmHIyEAIfkEAAoAAgAsAAAAABAAEAAABWAgII4j85Ao2hRIKgrEUBQJLaSHMe8zgQo6Q8sxS7RIhILhBkgumCTZsXkACBC+0cwF2GoLLoFXREDcDlkAojBICRaFLDCOQtQKjmsQSubtDFU/NXcDBHwkaw1cKQ8MiyEAIfkEAAoAAwAsAAAAABAAEAAABVIgII5kaZ6AIJQCMRTFQKiDQx4GrBfGa4uCnAEhQuRgPwCBtwK+kCNFgjh6QlFYgGO7baJ2CxIioSDpwqNggWCGDVVGphly3BkOpXDrKfNm/4AhACH5BAAKAAQALAAAAAAQABAAAAVgICCOZGmeqEAMRTEQwskYbV0Yx7kYSIzQhtgoBxCKBDQCIOcoLBimRiFhSABYU5gIgW01pLUBYkRItAYAqrlhYiwKjiWAcDMWY8QjsCf4DewiBzQ2N1AmKlgvgCiMjSQhACH5BAAKAAUALAAAAAAQABAAAAVfICCOZGmeqEgUxUAIpkA0AMKyxkEiSZEIsJqhYAg+boUFSTAkiBiNHks3sg1ILAfBiS10gyqCg0UaFBCkwy3RYKiIYMAC+RAxiQgYsJdAjw5DN2gILzEEZgVcKYuMJiEAOwAAAAAAAAAAAA==';
  47.  
  48. const defaultLocks = {
  49. Street: 1,
  50. Primary: 1,
  51. Minor: 2,
  52. Major: 3,
  53. Ramp: 4,
  54. Freeway: 4,
  55. POI: 1,
  56. Railroad: 1,
  57. Private: 1,
  58. Parking: 1,
  59. Offroad: 1,
  60. Narrow: 1,
  61. Camera: 4,
  62. RailroadCrossing: 3
  63. };
  64. const streets = {
  65. // fake element to show POI's locks
  66. 90000: {
  67. typeName: "POI",
  68. scan: true
  69. },
  70. 90001: {
  71. typeName: "Camera",
  72. scan: true
  73. },
  74. 90002: {
  75. typeName: "RailroadCrossing",
  76. scan: true
  77. },
  78. // normal streets
  79. 17: {
  80. typeName: "Private",
  81. scan: true
  82. },
  83. 20: {
  84. typeName: "Parking",
  85. scan: true
  86. },
  87. 8: {
  88. typeName: "Offroad",
  89. scan: true
  90. },
  91. 1: {
  92. typeName: "Street",
  93. scan: true
  94. },
  95. 2: {
  96. typeName: "Primary",
  97. scan: true
  98. },
  99. 7: {
  100. typeName: "Minor",
  101. scan: true
  102. },
  103. 6: {
  104. typeName: "Major",
  105. scan: true
  106. },
  107. 4: {
  108. typeName: "Ramp",
  109. scan: true
  110. },
  111. 3: {
  112. typeName: "Freeway",
  113. scan: true
  114. },
  115. 18: {
  116. typeName: "Railroad",
  117. scan: true
  118. },
  119. 22: {
  120. typeName: "Narrow",
  121. scan: true
  122. }
  123. };
  124. let relockObject = {};
  125. const userlevel = W.loginManager.user.rank + 1;
  126. //const userlevel = 6; // for testing purposes (NOTE: this does not enable you to lock higher!)
  127.  
  128. const requestsTimeout = 20000; // in ms
  129. const rulesHash = "AKfycbzKgUQL7cY6XMBlykq0JzJAPc1B26sKEAnG1RJokA9Wpgf_W0oZJwMKcrhA13LrUbvj";
  130. let rulesDB = {};
  131.  
  132. // Some functions
  133. function onScreen(obj) {
  134. if (obj.geometry) {
  135. return (W.map.getExtent().intersectsBounds(obj.geometry.getBounds()));
  136. }
  137. return (false);
  138. }
  139.  
  140. function hasPendingUR(poi) {
  141. return (poi.attributes.venueUpdateRequests.length > 0);
  142. }
  143.  
  144. function displayHtmlPage(res) {
  145. if (res.responseText.match(/Authorization needed/) || res.responseText.match(/ServiceLogin/)) {
  146. alert("LevelReset:\n" +
  147. "Authorization is required for using this script. This is one time action.\n" +
  148. "Now you will be redirected to the authorization page, where you'll need to approve request.\n" +
  149. "After confirmation, please close the page and reload WME.");
  150. }
  151. let w = window.open();
  152. w.document.open();
  153. w.document.write(res.responseText);
  154. w.document.close();
  155. w.location = res.finalUrl;
  156. }
  157.  
  158. function sendHTTPRequest(url, callback) {
  159. GM_xmlhttpRequest({
  160. url: url,
  161. method: 'GET',
  162. timeout: requestsTimeout,
  163. onload: function (res) {
  164. callback(res);
  165. },
  166. onreadystatechange: function (res) {
  167. // fill if needed
  168. },
  169. ontimeout: function (res) {
  170. alert("LevelReset: Sorry, request timeout!");
  171. },
  172. onerror: function (res) {
  173. alert("LevelReset: Sorry, request error!");
  174. }
  175. });
  176. }
  177.  
  178. function validateHTTPResponse(res) {
  179. let result = false,
  180. displayError = true;
  181. if (res) {
  182. switch (res.status) {
  183. case 200:
  184. displayError = false;
  185. if (res.responseHeaders.match(/content-type: application\/json/i)) {
  186. result = true;
  187. } else if (res.responseHeaders.match(/content-type: text\/html/i)) {
  188. displayHtmlPage(res);
  189. }
  190. break;
  191. default:
  192. displayError = false;
  193. alert("LevelReset Error: unsupported status code - " + res.status);
  194. console.log("LevelReset: " + res.responseHeaders);
  195. console.log("LevelReset: " + res.responseText);
  196. break;
  197. }
  198. } else {
  199. displayError = false;
  200. alert("LevelReset error: Response is empty!");
  201. }
  202.  
  203. if (displayError) {
  204. alert("LevelReset: Error processing request. Response: " + res.responseText);
  205. }
  206. return result;
  207. }
  208.  
  209. function getAllLockRules() {
  210. function requestCallback(res) {
  211. if (validateHTTPResponse(res)) {
  212. let out = JSON.parse(res.responseText);
  213. if (out.result == "success") {
  214. initUI(out.rules);
  215. } else {
  216. alert("LevelReset: Error getting locking rules!");
  217. }
  218. }
  219. }
  220.  
  221. const url = 'https://script.google.com/macros/s/' + rulesHash + '/exec?func=getAllLockRules';
  222. sendHTTPRequest(url, requestCallback);
  223. }
  224.  
  225. function initUI(rules) {
  226. let relockTab = document.createElement('li'),
  227. userInfo = document.getElementById('user-info'),
  228. navTabs = userInfo.querySelector('.nav-tabs'),
  229. tabContent = userInfo.querySelector('.tab-content'),
  230. relockContent = document.createElement('div'),
  231. relockTitle = document.createElement('h5'),
  232. relockSubTitle = document.createElement('h6'),
  233. rulesSubTitle = document.createElement('h6'),
  234. relockAllbutton = document.createElement('input'),
  235. relockSub = document.createElement('p'),
  236. versionTitle = document.createElement('p'),
  237. resultsCntr = document.createElement('div'),
  238. rulesCntr = document.createElement('div'),
  239. alertCntr = document.createElement('div'),
  240. hidebutton = document.createElement('div'),
  241. dotscntr = document.createElement('div'),
  242. inputDiv1 = document.createElement('div'),
  243. inputDiv2 = document.createElement('div'),
  244. includeAllSegments = document.createElement('input'),
  245. includeAllSegmentsLabel = document.createElement('label'),
  246. respectRouting = document.createElement('input'),
  247. respectRoutingLabel = document.createElement('label'),
  248. percentageLoader = document.createElement('div');
  249.  
  250. rulesDB = rules;
  251.  
  252. // Begin building
  253. relockContent.id = 'sidepanel-relockTab';
  254. relockContent.className = 'tab-pane';
  255. relockTitle.appendChild(document.createTextNode('Re-lock Segments & POI'));
  256. relockTitle.style.cssText = 'margin-bottom:0';
  257. relockTab.innerHTML = '<a href="#sidepanel-relockTab" data-toggle="tab" title="Relock segments">Re - <span class="fa fa-lock" id="lockcolor" style="color:green"></span></a>';
  258.  
  259. // fill tab
  260. relockSub.innerHTML = 'Your on-screen area is automatically scanned when you load or pan around. Pressing the lock behind each type will relock only those results, or you can choose to relock all.<br/><br/>You can only relock segments lower or equal to your current editor level. Segments locked higher than normal are left alone.';
  261. relockSub.style.cssText = 'font-size:85%;padding:15px;border:1px solid red;border-radius:5px;position:relative';
  262. relockSub.id = 'sub';
  263. hidebutton.style.cssText = 'cursor:pointer;width:16px;height:16px;position:absolute;right:3px;top:3px;background-image:url(\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAAWdEVYdENyZWF0aW9uIFRpbWUAMTEvMjAvMTVnsXrkAAADTUlEQVQ4jW2TW0xbZQCAv3ODnpYWegEGo1wKwzBcxAs6dONSjGMm3kjmnBqjYqLREE2WLDFTIBmbmmxRpzHy4NPi4zRLfNBlZjjtnCEaOwYDJUDcVqC3UzpWTkt7fp80hvk9f/nePkkIwWb+gA5jMXLQjK50Zc2cuKVp4wlX2UevtAYubnal/waWoTI1N38keu7ck2uTl335ZFJCkpE8XlGob4ibgeZvMl7P8MtdO6/dFohDe/Sn0LdzJ457MuHfUYqLkYtsSIqMJASyIiNv30Gm6+G1zNbqvpf6gqF/AwaUXx+/MDdz6KArH4ujVVRAbgPVroMsQz6P6nJiGUnUGj/pR/tTyx2dtW+11t2UAa5Pz34w//GHLitpsG1wkODp0xQ11GOZJpgmzq5uqo8ew76zAxFPUDJxscwzFR4BkGfh/tj58/3Zq9OoFZU0PHsAd00NnWNj6IEApd3duA48g2nXKenpQSl1oceWsUeuPfdp+M9GZf/zA5+lz3x9lxRbAUli+dIlKnt7Ud1uCk1NJH0+VnMmq6EQfw0NUzCSULBQfT4HVf4iNRO50VlIGSi6jup0sj5zlTO7d9N48iRLa2vkCwWsyTArbx/GAaSBm/MLyLm85OjZs0c2zawQsoRmt5NeXCRyeRLh9rBkGBSEwF6i09h+L96GemyAx2bDK4ENkGRJkbM2fVy4PRhT08RmZvH09VE29C6ixEFuahL3hklLby9PhEKUt7VRZln4kHD669Bqtl6Q7W07jqWL9FQiEkHTdUoGBsgXF5EPh0m8M8Tc62/CSoLSqmqaR4ZxaRpenxfbgw8lCy2Nx5Uv3xuNXEll7shO/HI38Rjr09NImkriyCgOy0JZTZM4+x3C7SY+epTaLZWsdwXJPNV/6jF/9ReSEIKzmcKWpbHPF9OHDxUr6xksoAiQJAmnpuEWAqeq4G9uRr7nPpZeeDG10NqybV+5Ly4DPGJXlsv79u51v38iK22/EwmwACEEIpdD2tjApmncan8A49XX4qtNgeC+cl/8tpm+jxoBY+K3N7I/jj+dvxKuIhZV7KpKWV295dy1K6YEg1/NO2wj+/210f+98R9+hub0wo1BOZnslRVV16orf0hVeD55HH7d7P4N0V1gY9/zcaEAAAAASUVORK5CYII=\');';
  264. hidebutton.onclick = function () {
  265. localStorage.msgHide = 1;
  266. $('#sub').hide('slow');
  267. };
  268. dotscntr.style.cssText = 'width:16px;height:16px;margin-left:5px;background:url("' + loader + '");vertical-align:text-top;display:none';
  269. dotscntr.id = 'dotscntr';
  270. relockSubTitle.innerHTML = 'Results';
  271. relockSubTitle.id = 'reshdr';
  272. rulesSubTitle.innerHTML = 'Active rules';
  273. versionTitle.innerHTML = 'Version ' + VERSION;
  274. versionTitle.style.cssText = 'margin:2px;font-size:85%;font-weight:bold';
  275. relockAllbutton.id = 'rlkall';
  276. relockAllbutton.type = 'button';
  277. relockAllbutton.value = 'Relock All';
  278. relockAllbutton.style.cssText = 'margin: 10px 3px 0 0';
  279. relockAllbutton.onclick = function () {
  280. relockAll();
  281. };
  282.  
  283. // Also reset higher locked segments?
  284. includeAllSegments.type = 'checkbox';
  285. includeAllSegments.name = "name";
  286. includeAllSegments.value = "value";
  287. includeAllSegments.checked = (localStorage.getItem('Relock_allSegments') == 'true');
  288. includeAllSegments.id = "_allSegments";
  289. includeAllSegments.onclick = function () {
  290. localStorage.setItem('Relock_allSegments', includeAllSegments.checked.toString());
  291. scanArea();
  292. relockShowAlert();
  293. };
  294. includeAllSegmentsLabel.htmlFor = "_allSegments";
  295. includeAllSegmentsLabel.innerHTML = 'Also reset higher locked objects';
  296. includeAllSegmentsLabel.style.cssText = 'font-size:95%;margin-left:5px;vertical-align:middle';
  297.  
  298. // Respect routing road type
  299. respectRouting.type = 'checkbox';
  300. respectRouting.name = "name";
  301. respectRouting.value = "value";
  302. respectRouting.checked = localStorage.getItem('Relock_respectRouting') == 'false' ? false : true;
  303. respectRouting.id = "_respectRouting";
  304. respectRouting.onclick = function () {
  305. localStorage.setItem('Relock_respectRouting', respectRouting.checked.toString());
  306. scanArea();
  307. };
  308. respectRoutingLabel.htmlFor = "_respectRouting";
  309. respectRoutingLabel.innerHTML = 'Respect routing road type';
  310. respectRoutingLabel.style.cssText = 'font-size:95%;margin-left:5px;vertical-align:middle';
  311.  
  312. resultsCntr.style.cssText = 'margin-right:5px;';
  313.  
  314. // add results empty list
  315. $.each(streets, function (key, value) {
  316. let __cntr = document.createElement('div'),
  317. __keyLeft = document.createElement('div'),
  318. __prntRight = document.createElement('div'),
  319. __cntRight = document.createElement('div'),
  320. __cleardiv = document.createElement("div"),
  321. __chkLeft = document.createElement('input'),
  322. __lblLeft = document.createElement('label');
  323. let idPrefix = 'Relock_' + value.typeName + '_';
  324.  
  325. // Begin building
  326. __keyLeft.style.cssText = 'float:left';
  327.  
  328. __chkLeft.type = 'checkbox';
  329. __chkLeft.checked = (localStorage.getItem(idPrefix + 'chk') == 'true');
  330. __chkLeft.id = idPrefix + 'chk';
  331. __chkLeft.onclick = function () {
  332. localStorage.setItem(idPrefix + 'chk', __chkLeft.checked.toString());
  333. scanArea();
  334. };
  335. __lblLeft.htmlFor = idPrefix + 'chk';
  336. __lblLeft.innerHTML = value.typeName;
  337. __lblLeft.style.cssText = 'margin-bottom:0px;font-weight:normal;';
  338.  
  339. __keyLeft.appendChild(__chkLeft);
  340. __keyLeft.appendChild(__lblLeft);
  341.  
  342. __cntRight.style.cssText = 'float:right';
  343. __cntRight.innerHTML = '-';
  344.  
  345. __prntRight.id = idPrefix + 'value';
  346. __prntRight.style.cssText = 'float:right';
  347. __prntRight.appendChild(__cntRight);
  348.  
  349. __cleardiv.style.cssText = 'clear:both;';
  350.  
  351. // Add to stage
  352. __cntr.appendChild(__keyLeft);
  353. __cntr.appendChild(__prntRight);
  354. __cntr.appendChild(__cleardiv);
  355. resultsCntr.appendChild(__cntr);
  356. });
  357.  
  358. // Alert box
  359. alertCntr.id = "alertCntr";
  360. alertCntr.style.cssText = 'border:1px solid #EBCCD1;background-color:#F2DEDE;color:#AC4947;font-weight:bold;font-size:90%;border-radius:5px;padding:10px;margin:5px 5px;display:none';
  361. alertCntr.innerHTML = 'Watch out for map exceptions, some higher locks are there for a reason!';
  362.  
  363. // Rules table
  364. let rowElm;
  365. let colElm;
  366.  
  367. let tableElm = document.createElement('table');
  368. tableElm.className = 'tg';
  369.  
  370. let bodyElm = document.createElement('tbody');
  371.  
  372. const topCountry = W.model.getTopCountry().abbr;
  373. const countryRules = rulesDB[topCountry];
  374. if (countryRules) {
  375. $.each(countryRules, function (key, value) {
  376. if (key == "CountryName") return false;
  377.  
  378. rowElm = document.createElement('tr');
  379. rowElm.className = "tg-row";
  380. rowElm.dataset.name = parseInt(key) === 0 ? 'country' : value.CityName; // need to hard code 'country' to identify later
  381.  
  382. colElm = document.createElement('td');
  383. colElm.className = "tg-header";
  384. colElm.innerHTML = parseInt(key) === 0 ? countryRules.CountryName : value.CityName;
  385. colElm.colSpan = 6;
  386. rowElm.appendChild(colElm);
  387. tableElm.appendChild(rowElm);
  388.  
  389. const maxCol = 3;
  390. let colIndex = 0;
  391. rowElm = document.createElement('tr');
  392. $.each(value.Locks, function (k, v) {
  393. if (v) {
  394. rowElm.className = "tg-row";
  395. rowElm.dataset.name = parseInt(key) === 0 ? 'country' : value.CityName; // need to hard code 'country' to identify later
  396. if (colIndex < maxCol) {
  397. colElm = document.createElement('td');
  398. colElm.className = "tg-type";
  399. colElm.innerHTML = k;
  400. rowElm.appendChild(colElm);
  401.  
  402. colElm = document.createElement('td');
  403. colElm.className = "tg-value";
  404. colElm.innerHTML = v;
  405. rowElm.appendChild(colElm);
  406.  
  407. colIndex++;
  408. } else {
  409. colIndex = 0;
  410. tableElm.appendChild(rowElm);
  411. rowElm = document.createElement('tr');
  412. }
  413. }
  414. });
  415. tableElm.appendChild(rowElm);
  416. });
  417. }
  418.  
  419. tableElm.appendChild(bodyElm);
  420. rulesCntr.style.cssText = 'font-size:12px';
  421. rulesCntr.appendChild(tableElm);
  422.  
  423. // add to stage
  424. navTabs.appendChild(relockTab);
  425. tabContent.appendChild(relockContent);
  426. relockContent.appendChild(relockTitle);
  427. relockContent.appendChild(versionTitle);
  428.  
  429. // Loader bar
  430. percentageLoader.id = 'percentageLoader';
  431. percentageLoader.style.cssText = 'width:1px;height:10px;background-color:green;margin-top:10px;border:1px solid:#333333;display:none';
  432.  
  433. // only show if user didn't hide it before
  434. if (localStorage.msgHide != 1) {
  435. relockSub.appendChild(hidebutton);
  436. relockContent.appendChild(relockSub);
  437. }
  438.  
  439. inputDiv1.appendChild(respectRouting);
  440. inputDiv1.appendChild(respectRoutingLabel);
  441. inputDiv2.appendChild(includeAllSegments);
  442. inputDiv2.appendChild(includeAllSegmentsLabel);
  443. relockContent.appendChild(inputDiv1);
  444. relockContent.appendChild(inputDiv2);
  445.  
  446. relockContent.appendChild(alertCntr);
  447. relockContent.appendChild(relockSubTitle);
  448. relockContent.appendChild(resultsCntr);
  449. relockContent.appendChild(relockAllbutton);
  450. relockContent.appendChild(dotscntr);
  451. relockContent.appendChild(percentageLoader);
  452. relockContent.appendChild(rulesSubTitle);
  453. relockContent.appendChild(rulesCntr);
  454.  
  455. // Do a default scan once at startup
  456. relockShowAlert();
  457. scanArea();
  458. }
  459.  
  460. function relock(obj, key) {
  461. let objects = obj[key];
  462. let _i = 0;
  463.  
  464. // update GUI
  465. function RunLocal() {
  466. W.model.actionManager.add(objects[_i]);
  467. _i++;
  468.  
  469. if (_i < objects.length) {
  470. setTimeout(RunLocal, 1);
  471. let newWidth = (_i / objects.length) * $('#sidepanel-relockTab').css('width').replace('px', '');
  472. $('#percentageLoader').show();
  473. $('#percentageLoader').css('width', newWidth + 'px');
  474. $('#dotscntr').css('display', 'inline-block');
  475. } else {
  476. $('#dotscntr').css('display', 'none');
  477. $('#percentageLoader').hide();
  478. }
  479. }
  480. RunLocal();
  481. }
  482.  
  483. function relockAll() {
  484. // only lock "all" until the current editors level is reached, then stop...
  485. $('#dotscntr').css('display', 'inline-block');
  486.  
  487. $.each(relockObject, function (key, value) {
  488. if (value.length !== 0) {
  489. // loop trough each segmentType
  490. let _i = 0;
  491. let RunLocal5 = function () {
  492. W.model.actionManager.add(value[_i]);
  493. _i++;
  494.  
  495. // Did not iterate with $.each, so the GUI can update with larger arrays
  496. if (_i < value.length) {
  497. setTimeout(RunLocal5, 1);
  498. let newWidth = (_i / value.length) * $('#sidepanel-relockTab').css('width').replace('px', '');
  499. $('#percentageLoader').show();
  500. $('#percentageLoader').css('width', newWidth + 'px');
  501. $('#dotscntr').css('display', 'inline-block');
  502. } else {
  503. $('#dotscntr').css('display', 'none');
  504. $('#percentageLoader').hide();
  505. }
  506. };
  507. RunLocal5();
  508. }
  509. });
  510. scanArea();
  511. $('#dotscntr').hide('slow');
  512. }
  513.  
  514. function relockShowAlert() {
  515. let includeAllSegments = document.getElementById('_allSegments');
  516. if (includeAllSegments && includeAllSegments.checked)
  517. $('#alertCntr').show("fast");
  518. else
  519. $('#alertCntr').hide("fast");
  520. }
  521.  
  522. function hideInactiveCities() {
  523. $('tr.tg-row').each(function (i) {
  524. let isActive = false;
  525. for (let j in W.model.cities.objects) {
  526. if (W.model.cities.objects[j].attributes.name == $(this).data("name")) {
  527. isActive = true;
  528. break;
  529. }
  530. }
  531. if (isActive || $(this).data("name") == 'country') {
  532. $(this).show("fast");
  533. } else {
  534. $(this).hide("fast");
  535. }
  536. });
  537. }
  538.  
  539. function setLockLevel(v, scanObj, desiredLockLevel) {
  540. let includeAllSegments = document.getElementById('_allSegments');
  541. let allSegmentsInclude = includeAllSegments.checked && userlevel > 4;
  542. if (userlevel > desiredLockLevel) {
  543. if ((v.attributes.lockRank < desiredLockLevel) ||
  544. (v.attributes.lockRank > desiredLockLevel && allSegmentsInclude)) {
  545. relockObject[scanObj].push(new UpdateObject(v, {
  546. lockRank: desiredLockLevel
  547. }));
  548. return true;
  549. }
  550. }
  551. return false;
  552. }
  553.  
  554. function scanArea() {
  555. let respectRouting = document.getElementById('_respectRouting');
  556. let relockSubTitle = document.getElementById('reshdr');
  557. let relockAllbutton = document.getElementById('rlkall');
  558.  
  559. if (!(relockSubTitle && relockAllbutton && respectRouting))
  560. return;
  561.  
  562. hideInactiveCities();
  563.  
  564. // Object with array of road types, to collect each wrongly locked segment, for later use
  565. $.each(defaultLocks, function (k, v) {
  566. relockObject[k] = [];
  567. });
  568.  
  569. let foundBadlocks = false;
  570. let respectRoutingRoadType = respectRouting.checked;
  571. let count = 0;
  572.  
  573. // Choose country lock settings. If country selection fails
  574. // or country isn't in this list, WME default values are used.
  575. let topCountry = W.model.getTopCountry().abbr;
  576. let ABBR = rulesDB[topCountry] ? rulesDB[topCountry][0].Locks : defaultLocks;
  577. console.log("LevelReset: ", ABBR);
  578.  
  579. // Do a count on how many segments are in need of a correct lock (limit to 150 to save CPU)
  580. // Count also depends on the users editor level
  581. const limitCount = 150;
  582. relockSubTitle.innerHTML = 'Results (limit: ' + limitCount + ')';
  583.  
  584. // disable unchecked road types
  585. $.each(streets, function (key, value) {
  586. let idPrefix = 'Relock_' + value.typeName + '_chk';
  587. let chk = document.getElementById(idPrefix);
  588. value.scan = (chk && chk.checked);
  589. });
  590.  
  591. // ============== POI ===========================
  592. if (streets["90000"].scan) {
  593. let scanObj = "POI";
  594. $.each(W.model.venues.objects, function (k, v) {
  595. if (count < limitCount && v.type == "venue" && onScreen(v) && v.isGeometryEditable() && !hasPendingUR(v) /*&& !v.isResidential()*/) {
  596.  
  597. let strt = v.attributes.streetID ? W.model.streets.objects[v.attributes.streetID] : null;
  598. let cityID = strt ? strt.cityID : null;
  599.  
  600. let desiredLockLevel = (cityID && rulesDB[topCountry] && rulesDB[topCountry][cityID]) ? rulesDB[topCountry][cityID].Locks[scanObj] : ABBR[scanObj];
  601. desiredLockLevel--;
  602.  
  603. if (setLockLevel(v, scanObj, desiredLockLevel)) {
  604. foundBadlocks = true;
  605. count++;
  606. }
  607. }
  608. });
  609. }
  610. // ============== Cameras ===========================
  611. if (streets["90001"].scan) {
  612. let scanObj = "Camera";
  613. $.each(W.model.cameras.objects, function (k, v) {
  614. if (count < limitCount && v.type == "camera" && onScreen(v) && v.isGeometryEditable()) {
  615.  
  616. let desiredLockLevel = ABBR[scanObj];
  617. desiredLockLevel--;
  618.  
  619. if (setLockLevel(v, scanObj, desiredLockLevel)) {
  620. foundBadlocks = true;
  621. count++;
  622. }
  623. }
  624. });
  625. }
  626. // ============== Railroad Crossings ===========================
  627. if (streets["90002"].scan) {
  628. let scanObj = "RailroadCrossing";
  629. $.each(W.model.railroadCrossings.objects, function (k, v) {
  630. if (count < limitCount && v.type == "railroadCrossing" && onScreen(v) && v.isGeometryEditable()) {
  631.  
  632. let desiredLockLevel = ABBR[scanObj];
  633. desiredLockLevel--;
  634.  
  635. if (setLockLevel(v, scanObj, desiredLockLevel)) {
  636. foundBadlocks = true;
  637. count++;
  638. }
  639. }
  640. });
  641. }
  642. // ============== Segments ===========================
  643. $.each(W.model.segments.objects, function (k, v) {
  644. if (count < limitCount && v.type == "segment" && onScreen(v) && v.isGeometryEditable()) {
  645. let curStreet = streets[v.attributes.roadType];
  646. // for changed routing respect the routing type (if enabled)
  647. if (v.attributes.routingRoadType && respectRoutingRoadType) {
  648. curStreet = streets[v.attributes.routingRoadType];
  649. }
  650. if (curStreet && curStreet.scan) {
  651. let strt = W.model.streets.getObjectById(v.attributes.primaryStreetID);
  652. let cityID = strt ? strt.cityID : null;
  653.  
  654. let stLocks = (cityID && rulesDB[topCountry] && rulesDB[topCountry][cityID]) ? rulesDB[topCountry][cityID].Locks : ABBR;
  655. let desiredLockLevel = stLocks[curStreet.typeName] - 1;
  656.  
  657. if (setLockLevel(v, curStreet.typeName, desiredLockLevel)) {
  658. foundBadlocks = true;
  659. count++;
  660. }
  661. }
  662. }
  663. });
  664.  
  665. // Build results to users tab panel
  666. $.each(relockObject, function (key, value) {
  667. let __lckRight = document.createElement('div');
  668. let __cntRight = document.createElement('div');
  669. let idPrefix = 'Relock_' + key + '_value';
  670.  
  671. // Begin building
  672. let __prntRight = document.getElementById(idPrefix);
  673. __prntRight.innerHTML = '';
  674.  
  675. __cntRight.style.cssText = 'float:right';
  676. __lckRight.style.cssText = 'width:15px;float:right;padding:2px 0 0 8px;cursor:pointer;';
  677.  
  678. if (value.length !== 0) {
  679. __cntRight.innerHTML = '<b>' + value.length + '</b>';
  680. __lckRight.className = 'fa fa-lock';
  681. __lckRight.style.cssText += 'color:red;';
  682. __lckRight.onclick = function () {
  683. relock(relockObject, key);
  684. };
  685. __prntRight.appendChild(__lckRight);
  686. } else {
  687. __cntRight.innerHTML = '-';
  688. }
  689.  
  690. __prntRight.appendChild(__cntRight);
  691. });
  692.  
  693. // Color the small lock icon red, if errors are found, so people can decide what to do...
  694. if (foundBadlocks) {
  695. relockAllbutton.removeAttribute('disabled');
  696. $('#lockcolor').css('color', 'red');
  697. } else {
  698. relockAllbutton.setAttribute('disabled', true);
  699. $('#lockcolor').css('color', 'green');
  700. }
  701. }
  702.  
  703. getAllLockRules();
  704.  
  705. // Register some event listeners
  706. W.map.events.register("moveend", null, scanArea);
  707. W.model.actionManager.events.register("afteraction", null, scanArea);
  708. W.model.actionManager.events.register("afterundoaction", null, scanArea);
  709. W.model.actionManager.events.register("noActions", null, scanArea);
  710. }
  711. setTimeout(LevelReset_bootstrap, 2000);